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.
Related
This question already has answers here:
How to write multiline inline assembly code in GCC C++?
(2 answers)
Closed 2 years ago.
I was compiling some code that had this piece of code:
__asm__ __volatile__ ("
pushw %%es
movw %%ds, %%ax
movw %%ax, %%es
xorl %%eax, %%eax
movl SurfBufD, %%edi
xorl %%ebx, %%ebx
Blank2:
movl SurfaceX, %%ecx
rep
stosw
addl Temp1, %%edi
subl SurfaceX, %%edi
subl SurfaceX, %%edi
addl $1, %%ebx
cmpl SurfaceY, %%ebx
jne Blank2
popw %%es
" : : : "cc", "memory", "eax", "ebx", "ecx", "edi");
and when I tried to compile it, I got:
linux/sdllink.c:948:24: warning: missing terminating " character
asm volatile ("
^
linux/sdllink.c:948:2: error: missing terminating " character
asm volatile ("
^
linux/sdllink.c:949:3: error: expected string literal before ‘pushw’
pushw %%es
^
linux/sdllink.c:966:51: warning: missing terminating " character
" : : : "cc", "memory", "eax", "ebx", "ecx", "edi");
^
linux/sdllink.c:966:2: error: missing terminating " character
" : : : "cc", "memory", "eax", "ebx", "ecx", "edi");
I tried to solve it changing this code to:
__asm__ __volatile__ (
"pushw %%es"
"movw %%ds, %%ax"
"movw %%ax, %%es"
"xorl %%eax, %%eax"
"movl SurfBufD, %%edi"
"xorl %%ebx, %%ebx"
"Blank2:"
"movl SurfaceX, %%ecx"
"rep"
"stosw"
"addl Temp1, %%edi"
"subl SurfaceX, %%edi"
"subl SurfaceX, %%edi"
"addl $1, %%ebx"
"cmpl SurfaceY, %%ebx"
"jne Blank2"
"popw %%es"
" : : : cc, memory, eax, ebx, ecx, edi");
Basically, I assumed this function wanted every line to be a string literal, but it didn't change anything. So, what I have to do?
One string literal in C cannot written in multiple lines, but consecutive string literals are merged.
Also \ in the line end means that the line should be concatenated with the next line and treated as one line, so you can use this.
There should be newlines in the string. Newlines can be expressed as \n.
Consecutive string literals:
__asm__ __volatile__ (
"pushw %%es\n"
"movw %%ds, %%ax\n"
"movw %%ax, %%es\n"
"xorl %%eax, %%eax\n"
"movl SurfBufD, %%edi\n"
"xorl %%ebx, %%ebx\n"
"Blank2:\n"
"movl SurfaceX, %%ecx\n"
"rep\n"
"stosw\n"
"addl Temp1, %%edi\n"
"subl SurfaceX, %%edi\n"
"subl SurfaceX, %%edi\n"
"addl $1, %%ebx\n"
"cmpl SurfaceY, %%ebx\n"
"jne Blank2\n"
"popw %%es\n"
: : : "cc", "memory", "eax", "ebx", "ecx", "edi");
Lines connected via \:
__asm__ __volatile__ (
"pushw %%es\n\
movw %%ds, %%ax\n\
movw %%ax, %%es\n\
xorl %%eax, %%eax\n\
movl SurfBufD, %%edi\n\
xorl %%ebx, %%ebx\n\
Blank2:\n\
movl SurfaceX, %%ecx\n\
rep\n\
stosw\n\
addl Temp1, %%edi\n\
subl SurfaceX, %%edi\n\
subl SurfaceX, %%edi\n\
addl $1, %%ebx\n\
cmpl SurfaceY, %%ebx\n\
jne Blank2\n\
popw %%es\n"
: : : "cc", "memory", "eax", "ebx", "ecx", "edi");
I'm working on a code that checks if the program is running under VM or VPC in C and I have some errors in the inline ASM at compile-time.
This is my code so far:
bool IsInsideVPC()
{
bool rc = false;
try
{
__asm__(
"push %ebx\n\t"
"movl $0, %ebx\n\t" // Flag
"movl $1, %eax"); // VPC function number
// call VPC
asm __volatile__ (".byte 0x0F");
asm __volatile__ (".byte 0x3F");
asm __volatile__ (".byte 0x07");
asm __volatile__ (".byte 0x0B");
__asm__(
"test %ebx, %ebx\n\t"
"movl $1, $rc\n\t" // Flag
"pop %ebx");
}
catch (...)
{
// The except block shouldn't get triggered if VPC is running!!
}
return rc;
}
bool IsInsideVMWare()
{
bool rc = false;
try
{
__asm__(
"push %edx\n\t"
"push %ecx\n\t" // Flag
"push %ebx\n\t"
"movl 'VMXh', %eax\n\t"
"movl $0, %ebx\n\t"
"movl $10, %ecx\n\t"
"movl 'VX', %edx\n\t"
"in %eax, %dx\n\t"
"cmp %ebx, 'VMXh'\n\t"
"movl $1, $rc\n\t"
"pop %ebx\n\t"
"pop %ecx\n\t"
"pop %edx");
}
catch (...)
{
rc = false;
}
return rc;
}
Ofcourse after all this, there is the main function that runs eveything, checks the results and outputs an answer.
I didn't write the original code, but I did changed it to the GCC syntax.
I'm getting errors that I think are related to the way I insert a string into a register.
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.
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.
__asm__ (
"loop:\n\t"
"movl $1,%3\n\t"
"movl $0, %6\n"
"start:\n\t"
"movl (%1,%3,4),%4\n\t"
"movl -4(%1, %3, 4), %5\n\t"
"cmpl %4, %5\n\t"
"jle next\n\t"
"xchgl %4, %5\n\t"
"movl %4, (%1, %3, 4)\n\t"
"movl %5, -4(%1, %3, 4)\n\t"
"movl $1, %6\n"
"next:\n\t"
"incl %3\n\t"
"cmpl %3, %2\n\t"
"jge start\n\t"
"cmpl $0, %6\n\t"
"je end\n\t"
"jmp loop\n"
"end: \n\t"
:"=r"(input_array)
:"r"(input_array), "r"(size-1), "r"(1), "r"(0), "r"(0), "r"(0)
);
I get:
error: can't find a register in class ‘GENERAL_REGS’ while reloading ‘asm’ error: ‘asm’ operand has impossible constraints
You have to remember that these machines have a limited number of registers. And its possible to actually run out - that's what the error you're getting is telling you.
On x86, there are only 8 general-purpose registers. esp is reserved for the stack pointer. ebp is probably in use as a base-pointer. So that leaves only 6.
However, your inline assembly snippet appears to want 7 registers? You don't have enough of them.
So the solution is that you will need to use fewer registers. Put some of the parameters in memory or change the algorithm...