I have a code in C where the main tak is written in Assembly. The idea of the programm is to for example when x = abc def ,and y = a it deletes the word where at least one letter is the same and writes words without the same letters so it would write def. I have wrotten a code, but it gives error like :
prog.c:10: Error: no such instruction: `addl $112,%esp'
prog.c:12: Error: no such instruction: `xorl %eax,%eax'
prog.c:13: Error: no such instruction: `popl %ebx'
prog.c:16: Error: no such instruction: `popl %esi'
Here is the code :
#include <stdio.h>
#include <string.h>
int main(){
char *x = "asbc4a2bab ";
char *y = "ab";
char bufor[100];
asm volatile (
".intel_syntax noprefix;"
"mov ecx,%0;"
"push ecx;" //wrzuca na stos
"mov ecx,%1;"
"mov eax,%2;"
"call zadanie1;"
"jmp wyjscie;"
"zadanie1:"
"push ebp;" //wrzucamy ebp na stos
"push eax;"
"push ecx;" //ecx zliczanie
"push edi;" //edi destination
"mov ebp,esp;" //do ebp adres stosu
"mov esi,[ebp+20];" //esi bezposrednio do x
"mov edi,[ebp+4];" //edi adres y
"mov ebx,[ebp+8];"//ebx bufor
"mov eax,0;"//eax to false
"push eax;"
"push esi;"
"push eax;"
"etykieta_x:"
"mov eax,[esp+8];"
"cmp eax,0;"
"je etykieta_y;"
"mov [esp+4],esi;"
"mov eax,0;"
"mov [esp+8],eax;"
//"mov [esp+4],esi;"
"etykieta_y:"
"mov eax,[edi];"
"cmp eax,'\0';" //porownoje eax z koncem
"je koniec_etykiety_x;"
"add edi,1;"//zwiekszamy petle
"cmp eax,[esi];"//porownoje y i x
"jne etykieta_y;"//wrocimy do etykiety y jesli nie sa rowne
"ustaw_flage:"
"pop eax;"
"mov eax,1;" //ustawia flage
"push eax;"
"koniec_etykiety_x:"
"pop eax;"
"cmp eax,1;"
"jne iteruj_dalej;"
"mov eax,0;"
"push eax;"
"iteruj_po_znakach:"
"add esi,1;"
"mov eax,[esi];"
"cmp eax,'\0';"
"je koniec;"
"cmp eax,' ';"
"je spacja_wykryta;"
"jmp etykieta_x;"
"spacja_wykryta:"
"mov eax,1;"
"mov [esp+8],eax;"
"jmp iteruj_po_znakach;"
"iteruj_dalej:"
"mov eax,0;"
"push eax;"
"add esi,1;"//zwiekszamy adres
"mov eax,[esi];"//pobieramhy nast zznak
"cmp eax,'\0';"
"je zapisz_do_bufora;"
"cmp eax,' ';"
"je spacja_wykryta_2;"
"mov eax,[esp+8];"
"cmp eax,0;"
"je etykieta_x;"
"jmp zapisz_do_bufora;"
"spacja_wykryta_2:"
"mov eax,1;"
"mov [esp+8],eax;"
"jmp iteruj_dalej;"
"zapisz_do_bufora:"
"mov eax,[esp+4];"
"interuj_po_slowie:"
"mov edx,[eax];"
"cmp edx,' ';"
"je etykieta_x;"
"cmp edx, '\0';"
"je etykieta_x;"
"mov [ebx],edx;"
"add eax,1;"
"add ebx,1;"
"jmp iteruj_po_slowie;"
"koniec:"
"pop edi;" //zdejmuje ze stosu
"pop ecx;"
"pop eax;"
"pop ebp;"
"ret;" //wyjdzie z funkcji
"wyjscie:"
".att_syntax_prefix;"
:
:"r"(x), "r"(y), "r"(bufor)
:"eax", "ecx"
);
return 0;
}
and here is the ideone link : http://ideone.com/wHFeDK
Someone know what may be wrong ? Thanks for help.
It's a horrible hack to manually switch syntax mode in inline asm and it might not work if you have any argument substitutions. The correct way is to use -masm=intel if you want intel syntax.
That said, your problem is that you have a typo in the directive where you wanted to restore the mode: you have .att_syntax_prefix instead of .att_syntax prefix (notice you don't need another underscore before prefix).
Also, the '\0' won't work, you should just use 0.
And, you have a typo: interuj_po_slowie vs iteruj_po_slowie.
PS: Stackoverflow is an english language forum, please post code in english, and comment it properly.
Related
In C I have:
__asm__ (
"mov $0x2,%rax;"
"mov $0x6000dd,%rdi;"
"mov $0x0,%rsi;"
"syscall;"
);
But when I comppile it in the assembly file I see:
# 12 "mine.cxx" 1
mov $0x2,%rax;mov $0x6000dd,%rdi;mov $0x0,%rsi;syscall;
why they are in 1 line like this
How to separate them?
You should add \n to separate lines.
__asm__ (
"mov $0x2,%rax;\n"
"mov $0x6000dd,%rdi;\n"
"mov $0x0,%rsi;\n"
"syscall;\n"
);
Adding \n will be helpful for you.
__asm__ (
"mov $0x2,%rax;\n"
"mov $0x6000dd,%rdi;\n"
"mov $0x0,%rsi;\n"
"syscall;\n"
);
everyone.
I am trying to use the inline assembly technique in c programs.
But, An error : operand type mismatch for 'mov', 'out' occurs when compiling.
My code
#define updateCursor(X, Y)({
__asm__ volatile(
"mov %%al, $0x0f \n\t"
"mov %%dx, $0x03d4 \n\t"
"out %%dx, %%al \n\t"
"mov %%al, %[x] \n\t" // No-Error
"mov %%dx, $0x03d5 \n\t"
"out %%dx, %%al \n\t"
:: (x) "m" (X)
: "al", "dx");
})
I do not understand why I get an error on almost every line. (except for the no-error part)
I am very grateful if you help me with what is wrong and how to fix it.
I have to count the number of words in a string that you get as an argument from the command line.
First I made this program:
#include <stdio.h>
#include <string.h>
int main( int argc, char *argv[] ){
char* s;
if(argc==1)
{
s="";
} else {
s = argv[1];
}
//char* s = " aqr b qabxx xryc pqr"; example
int x;
asm volatile(
".intel_syntax noprefix;"
"mov eax,%1;"
"xor edx,edx;"
"jmp petla;"
"petla0:"
"inc eax;"
"petla:"
"cmp [eax],byte ptr 0;"
"jz wyjscie;"
"cmp [eax],byte ptr 32;"
"jz petla0;"
"inc edx;"
"petla1:"
"inc eax;"
"cmp [eax],byte ptr 0;"
"jz wyjscie;"
"cmp [eax],byte ptr 32;"
"jz petla;"
"jmp petla1;"
"wyjscie:"
"mov %0,edx;"
".att_syntax prefix;"
: "=r" (x)
: "r" (s)
: "eax","edx"
);
printf("%hd\n",x);
return 0;
}
and it works fine; I get 5 as answer for "aqr b qabxx xryc pqr". But I need my program written only using assembly code. Something like this:
.intel_syntax noprefix
.globl main
.text
main:
mov ecx,?
?<- here is the issue: I don't know how to get an argument from the command line and access it as a char *.
xor edx,edx
jmp petla
petla0:
inc ecx
petla:
cmp byte ptr [ecx],0
jz wyjscie
cmp byte ptr [ecx],32
jz petla0
inc edx
petla1:
inc ecx
cmp byte ptr [ecx],0
jz wyjscie
cmp byte ptr [ecx], 32
jz petla
jmp petla1
wyjscie:
push edx
push offset msg
call printf
add esp, 8
mov edx,0
ret
.data
msg: .ascii "number of words=%d\n"
So first, let's look at your "working" code. While it works, there are a few "teachable" items here.
First of all, please get in the habit of using comments in your code. I realize English is not your first language so I probably couldn't read your comments, but still, you should have them.
Second, stop using ; to terminate your asm instructions. Yes, it looks a little clunkier to use \n\t, but when you use gcc's -S to output the assembler (a great way to see what's really going on), your code will be a mess without \n\t.
So far, that gets us:
asm volatile(
".intel_syntax noprefix\n\t"
// %1 is read-only, so use eax as temp
"mov eax,%1\n\t"
// # of words found
"xor edx,edx\n\t"
"jmp petla\n"
// Skip over spaces
"petla0:\n\t"
"inc eax\n"
"petla:\n\t"
"cmp [eax],byte ptr 0\n\t"
"jz wyjscie\n\t" // End of string
"cmp [eax],byte ptr 32\n\t"
"jz petla0\n\t" // Another space
// Starting new word
"inc edx\n"
// Walk the rest of the current word
"petla1:\n\t"
"inc eax\n\t"
"cmp [eax],byte ptr 0\n\t"
"jz wyjscie\n\t" // End of string
"cmp [eax],byte ptr 32\n\t"
"jz petla\n\t" // End of word
"jmp petla1\n" // Not end of word
"wyjscie:\n\t"
"mov %0,edx\n\t"
".att_syntax prefix"
: "=r" (x)
: "r" (s)
: "eax","edx"
);
Third, you need to understand that when using extended asm, %0 is just a way to refer to whatever is being passed in as the first argument. In this case, you specify that it must be a register ("=r"). So the value is already a register. Instead of using both edx and %0, you can store the count directly in %0.
Fourth, the purpose of byte ptr is so the assembler knows whether [eax] means: The byte at [eax], the word as [eax], the dword at [eax], etc. Such being the case, it is more commonly placed on the other side of a cmp instruction:
asm volatile(
".intel_syntax noprefix\n\t"
// %1 is read-only, so use eax as temp
"mov eax,%1\n\t"
// # of words found
"xor %0,%0\n\t"
"jmp petla\n"
// Skip over spaces
"petla0:\n\t"
"inc eax\n"
"petla:\n\t"
"cmp byte ptr [eax], 0\n\t"
"jz wyjscie\n\t" // End of string
"cmp byte ptr [eax], ' '\n\t"
"jz petla0\n\t" // Another space
// Starting new word
"inc %0\n"
// Walk the rest of the current word
"petla1:\n\t"
"inc eax\n\t"
"cmp byte ptr [eax], 0\n\t"
"jz wyjscie\n\t" // End of string
"cmp byte ptr [eax], ' '\n\t"
"jz petla\n\t" // End of word
"jmp petla1\n" // Not end of word
"wyjscie:\n\t"
".att_syntax prefix"
: "=r" (x)
: "r" (s)
: "eax","edx"
);
What's next? Oh yeah. When you use jz or jnz, if it doesn't jump, the code falls thru to the next instruction. This means that this:
"cmp byte ptr [eax], 0\n\t"
"jz wyjscie\n\t" // End of string
"cmp byte ptr [eax], ' '\n\t"
"jz petla\n\t" // End of word
"jmp petla1\n" // Not end of word
"wyjscie:\n\t"
Can be done like this:
"cmp byte ptr [eax], 0\n\t"
"jz petla\n\t" // End of word
"cmp byte ptr [eax], ' '\n\t"
"jnz petla1\n\t" // Not end of string
"wyjscie:\n\t"
As a general rule, I avoid doing memory reads multiple times. So where you do:
"cmp byte ptr [eax], 0\n\t"
"cmp byte ptr [eax], ' '\n\t"
I would do:
"mov dl, [eax]\n\t"
"cmp dl, 0\n\t"
"cmp dl, ' '\n\t"
This also lets us get rid of the byte ptr. dl can only hold a byte, so that must be what we are reading.
Another subtle point: In your original code, when you are walking the letters, if you encounter a space, you jump back to petla, where you check again to see if it is a space instead of to petla0 to read the next byte.
And 2 other nits: When comparing something with zero, I use test instead of cmp (generates slightly better code). And while it does exactly the same thing, when I compare 2 values (cmp edx, ' '), I find it easier to think in terms of "Are these things 'equal'" rather than "Is the difference between them zero?" As a result, I would use je instead of jz.
Putting all this together gives me:
asm (
".intel_syntax noprefix\n\t"
// %1 is read-only, so use eax as temp
"mov eax, %1\n\t"
// # of words found
"xor %0,%0\n"
// Skip over spaces
"petla0:\n\t"
"mov dl, [eax]\n\t"
"inc eax\n\t"
"test dl, dl\n\t"
"jz wyjscie\n\t" // End of string
"cmp dl, ' '\n\t"
"je petla0\n\t" // Another space
// Starting new word
"inc %0\n"
// Walk the rest of the current word
"petla1:\n\t"
"mov dl, [eax]\n\t"
"inc eax\n\t"
"cmp dl, ' '\n\t"
"je petla0\n\t" // end of word
"test dl, dl\n\t"
"jnz petla1\n" // not end of string
"wyjscie:\n"
".att_syntax prefix;"
: "=r" (x)
: "r" (s)
: "eax", "edx", "cc", "memory"
);
I also removed the volatile. Since you are using the output (by printing x), this is not required.
I will let you roll any of this that you want to keep into your pure asm by yourself.
As for why your pure asm doesn't work, I'm not on linux, so I can't run this. However, I don't see anything actually wrong with your counting code. You might look at this for accessing the command line arguments, but what you are doing should not give you 1.
How are you specifying your command line? I suspect you are not using the " marks around your string: a.out " aqr b qabxx xryc pqr". This would cause each word to be treated as a separate (null terminated) argument.
Edit 1: After some more reading, it looks like the pointer to argv[1] really should be at [esp + 8]. At least on linux. You aren't on Windows, right? Pretty sure it uses a different scheme.
You can try this to make sure your asm is working correctly, but I'm pretty sure that isn't your problem.
lea ecx, str
// Down by .data add:
str: .ascii " asdf adfs asd f adsf "
You can try using the msg format string you have to print argc. If you are passing the arguments correctly, this should be 2.
Change your msg to use %s, and print out the value from argv[0] (aka [esp+4]). This should be the program name.
Using that %s, you can print out argv[1].
I've looked at all the suggested threads on how to solve this, and i cant find one that matches my mistake.
When i compile i get "too many memory references for 'mov'", even if i take out all of them...?
__asm__(
"mov 0x8(%ebp), %edx;"
"mov 0x8(%edx), %edx;"
"cmp $0x0, %edx;"
"je notFound;"
"sub $0x10, %esp;"
"movl 0xc(%ebp), (%esp);"
"movl $0x24, 0x8(%esp);"
"mainloop: "
"movl %edx, 0x4(%esp);"
"call _memcmp;"
"cmp $0xffffffff, %eax;"
"je leftBranch;"
"cmp $0x1, %eax;"
"je rightBranch;"
"jne found;"
"leftBranch: "
"mov 0xc(%edx), %edx;"
"cmp $0x0, %edx;"
"je notFound;"
"jne mainloop;"
"rightBranch: "
"mov 0x10(%edx), %edx;"
"cmp $0x0, %edx;"
"je notFound;"
"jne mainloop;"
"notFound: "
"mov $0x0, %eax;"
"add $0x10, %esp;"
"leave;"
"ret;"
"found: "
"add $0x10, %esp;"
"leave;"
"ret;"
);
The problem is likely this line:
"movl 0xc(%ebp), (%esp);"
You can't reference two memory locations in a single mov instruction.
I have a huge problem with printing the specific word backwards. I'm trying to find words with '*' at the beggining and print them backwards, the rest should be printed normally.
For example:
Input: aaa1 ab0 1kk *ddd *lel 2cccc2 c1
Output aaa1 ab0 1kk ddd* lel* 2cccc2 c1
All I have is finding the words, finding the ones with '' and printing normally the words without ''.
Please help me and thank you in advance for your attention to this matter...
Have to write it in C language and here's my code
int main() {
char *x = "aaa1 ab0 1kk *ddd *lel
2cccc2 c1";
char bufor[100];
asm volatile (
".intel_syntax noprefix;"
"mov eax, %0;"
"push eax;"
"mov eax, %1;"
"push eax;"
"call zadanie1;"
"jmp wyjscie;"
"zadanie1:"
//
// FUNCTION START
//
"pushad;"
"mov esi, [esp+40];"
"mov edx, [esp+36];"
"push edx;"
"xor ecx, ecx;"
// MAIN LOOP - WORDS SEARCHING
"zad_loop:"
"mov edx, [esp];"
"lodsb;"
"test al, al;"
"jz zad_loop_end;"
"cmp al, 0x20;"
"jz zad_loop_end;"
"mov [edx+ecx], al;"
"inc ecx;"
"jmp zad_loop;"
// MAIN LOOP END
"zad_loop_end:"
"mov [edx+ecx], ch;"
"push eax;"
"push ecx;"
"test ecx, ecx;"
"jz not_print;"
// IS THE FIRST CHAR '*'
"lea eax, [edx];"
"mov al, [eax];"
"cmp al, '*';"
"jz backwards;"
"test al, al;"
"jz not_print;"
// PRINTING THE WORD WITHOUT '*'
"mov edx, [esp];"
"mov ecx, [esp+8];"
"mov ebx, 1;"
"push eax;"
"mov eax, 4;"
"int 0x80;"
"push 0x20;"
"call print_char;"
"pop eax;"
// PRINTING THE WORD WITH '*' - BACKWARDS
"backwards:"
// SKIP PRINTING
"not_print:"
"pop ecx;"
"pop eax;"
"xor ecx, ecx;"
"test al, al;"
"jnz zad_loop;"
// FUNCTION END
"pop edx;"
"push 0x0A;"
"call print_char;"
"popad;"
"ret 8;"
// CHAR OUTPUT
"print_char:"
"pushad;"
"mov edx, 1;"
"lea ecx, [esp+36];"
"mov ebx, 1;"
"mov eax, 4;"
"int 0x80;"
"popad;"
"ret 4;"
"wyjscie:"
".att_syntax prefix;"
:
: "r" (x), "r" (bufor)
: "eax"
);
return 0;
}
Designate a register to be a counter (pick any one you aren't using for other stuff) and set its value to 0.
When you hit a * character, push characters onto the stack until it finds a blank, incrementing the counter with each push.
When a blank is found, pop characters off the stack, decrementing the counter and printing the character each time, until the counter is 0.
I don't know your compiler, but I think your compiler would insert the code that you wrote as text in variables instead of compiling the instructions, because a text that begins with a " will be interpreted as text. Drop these chars.