Reputation: 15099
I'm trying to get a local variable defined in the caller from the callee via EBP. It should be possible, but if it's not, please explain why.
This is the code I have right now:
#include <stdio.h>
void TEST(int a, int b, int c){
int answer;
printf("a: %d | b: %d | c: %d\n", a, b, c);
__asm__ __volatile__(
".intel_syntax;"
"mov %0, dword ptr ds:[ebp + 20];" <-- EBP+20 == d == 42
".att_syntax;"
: "=r" (answer)
:
:
);
printf("Answer: %d\n", answer);
}
int main(void){
int a = 13;
int b = 14;
int c = 15;
int d = 42;
TEST(a, b, c);
}
By the time TEST
gets called I expect the stack to look the following way:
|+20| | 13 <-- d
|+16| | 14 <-- c
|+12| | 15 <-- b
|+ 8| | 42 <-- a
|+ 4| | return address
| 0| | EBP
|- 4| | local var answer
|- 8| | ...
If I try to compile the following code I get:
test.c: Assembler messages:
test.c:7: Error: segment register name expected
Where is the error?
Upvotes: 1
Views: 303
Reputation: 1318
I guess your example is for educational purposes only, so it's ok.
But generally be aware that you cannot rely on the order of variables on the stack. (You can't even rely on finding them on the stack).
For example if you make d
an int d[1] = {42}
several compilers will emit d,a,b,c
instead of a,b,c,d
. And if you turn on the optimizer everything can happen (and why would you use inline assembly mixed with unoptimized C code?).
Upvotes: 1
Reputation: 3670
move mem2,mem1
is not allowed.But this will be handled by gcc even on intel syntax. my assumtion was incorrect. Gcc
will generate correct code for both intel
and at&t
syntax.
"movl mem1,%0"
: "=r" (mem2)
Gcc will generate valid code for us:
mov mem1,%eax
mov %eax,mem2
gcc cant get segment register name.But there is segment ds
register.Plus it should be ok even without mentioning segment register.Actual problem was just prefix problem
Should be done:
to solve this we have to use nonprefix
or put prefixes %
Its on x64 machine. you should change rbp->ebp. and also 0x10 can be changed
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void TEST(int a, int b, int c) {
int answer;
int x = 16;
__asm__ __volatile__(
".intel_syntax noprefix ;"
"mov %0, dword ptr ds:[rbp + %1+0];"
".att_syntax;"
: "=r" (answer)
: "r"((uintptr_t)x) /* x is input operand */
);
printf("Answer: %d\n", answer);
__asm__ __volatile__(
" movl 0(%%rbp,%1,1),%0"
: "=r" (answer)
: "r"((uintptr_t)x) /* x is input operand */
);
printf("Answer: %d\n", answer);
__asm__ __volatile__(
"movl 0x10(%%rbp),%0"
: "=r" (answer)
);
printf("Answer: %d\n", answer);
__asm__ __volatile__(
".intel_syntax;"
"mov %0, dword ptr [%%rbp + 0x10];"
".att_syntax;"
: "=r" (answer)
);
printf("Answer: %d\n", answer);
//the same as you wrote, just I added noprefix
__asm__ __volatile__(
".intel_syntax noprefix ;"
"mov %0, dword ptr ds:[rbp + 0x10];"
".att_syntax;"
: "=r" (answer)
);
printf("Answer: %d\n", answer);
//this lines just to test if we refer the same address as address of d
void *addressd;
__asm__ __volatile__(
"lea 0x10(%%rbp),%0"
: "=r" (addressd)
);
printf("TEST: address of d %p\n", addressd);
}
int main(void) {
int a = 13;
int b = 14;
int c = 15;
int d = 42;
TEST(a, b, c);
printf("address of d %p", &d);
}
Upvotes: 1