Related
I am writing a C program that calls an x86 Assembly function which adds two numbers. Below are the contents of my C program (CallAssemblyFromC.c):
#include <stdio.h>
#include <stdlib.h>
int addition(int a, int b);
int main(void) {
int sum = addition(3, 4);
printf("%d", sum);
return EXIT_SUCCESS;
}
Below is the code of the Assembly function (my idea is to code from scratch the stack frame prologue and epilogue, I have added comments to explain the logic of my code) (addition.s):
.text
# Here, we define a function addition
.global addition
addition:
# Prologue:
# Push the current EBP (base pointer) to the stack, so that we
# can reset the EBP to its original state after the function's
# execution
push %ebp
# Move the EBP (base pointer) to the current position of the ESP
# register
movl %esp, %ebp
# Read in the parameters of the addition function
# addition(a, b)
#
# Since we are pushing to the stack, we need to obtain the parameters
# in reverse order:
# EBP (return address) | EBP + 4 (return value) | EBP + 8 (b) | EBP + 4 (a)
#
# Utilize advanced indexing in order to obtain the parameters, and
# store them in the CPU's registers
movzbl 8(%ebp), %ebx
movzbl 12(%ebp), %ecx
# Clear the EAX register to store the sum
xorl %eax, %eax
# Add the values into the section of memory storing the return value
addl %ebx, %eax
addl %ecx, %eax
I am getting a segmentation fault error, which seems strange considering that I think I am allocating memory in accordance with the x86 calling conventions (e.x. allocating the correct memory sections to the function's parameters). Furthermore, if any of you have a solution, it would be greatly appreciated if you could provide some advice as to how to debug an Assembly program embedded with C (I have been using the GDB debugger but it simply points to the line of the C program where the segmentation fault happens instead of the line in the Assembly program).
Your function has no epilogue. You need to restore %ebp and pop the stack back to where it was, and then ret. If that's really missing from your code, then that explains your segfault: the CPU will go on executing whatever garbage happens to be after the end of your code in memory.
You clobber (i.e. overwrite) the %ebx register which is supposed to be callee-saved. (You mention following the x86 calling conventions, but you seem to have missed that detail.) That would be the cause of your next segfault, after you fixed the first one. If you use %ebx, you need to save and restore it, e.g. with push %ebx after your prologue and pop %ebx before your epilogue. But in this case it is better to rewrite your code so as not to use it at all; see below.
movzbl loads an 8-bit value from memory and zero-extends it into a 32-bit register. Here the parameters are int so they are already 32 bits, so plain movl is correct. As it stands your function would give incorrect results for any arguments which are negative or larger than 255.
You're using an unnecessary number of registers. You could move the first operand for the addition directly into %eax rather than putting it into %ebx and adding it to zero. And on x86 it is not necessary to get both operands into registers before adding; arithmetic instructions have a mem, reg form where one operand can be loaded directly from memory. With this approach we don't need any registers other than %eax itself, and in particular we don't have to worry about %ebx anymore.
I would write:
.text
# Here, we define a function addition
.global addition
addition:
# Prologue:
push %ebp
movl %esp, %ebp
# load first argument
movl 8(%ebp), %eax
# add second argument
addl 12(%ebp), %eax
# epilogue
movl %ebp, %esp # redundant since we haven't touched esp, but will be needed in more complex functions
pop %ebp
ret
In fact, you don't need a stack frame for this function at all, though I understand if you want to include it for educational value. But if you omit it, the function can be reduced to
.text
.global addition
addition:
movl 4(%esp), %eax
addl 8(%esp), %eax
ret
You are corrupting the stacke here:
movb %al, 4(%ebp)
To return the value, simply put it in eax. Also why do you need to clear eax? that's inefficient as you can load the first value directly into eax and then add to it.
Also EBX must be saved if you intend to use it, but you don't really need it anyway.
Consider the following code for producing a list of numbers from 0 to 9 along with values of 2 and -3 raised to the power of the corresponding number from the list:
#include <stdio.h>
int power(int m, int n);
main()
{
int i;
for (i = 0; i <= 10; ++i)
printf("%d %d %d\n", i, power(2, i), power(-3, i));
return 0;
}
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
// return statement purposefully omitted. //
}
Of course the program does not work properly without the return statement for the power function, however by running the written code I get the following output:
0 1 1
1 2 2
2 3 3
3 4 4
4 5 5
5 6 6
6 7 7
7 8 8
8 9 9
9 10 10
And I'm wondering where are the numbers in the second and third column of the output coming from? In lack of a valid return value of power, the control transfers back to the calling function, but why does it output these numbers?
As pointed out by #dyukha and #Daniel H, the value returned is "whatever is in your EAX register". Your function finishes on a for-loop, hence the last instruction realized before returning (ending the function) probably was a branching test, to check if i <= n (your loop condition). You can actually check on what variable is set to your EAX register by using your compiler to generate the assembly version of your code (option -S). You may try to follow what values are set into your register before the call to
popq %rbp
retq
at the end of your function.
On my computer, I tried with Apple LLVM version 9.0.0 (clang-900.0.39.2), which generate the following for my function:
movl %edi, -8(%rbp)
movl %esi, -12(%rbp)
movl $1, -20(%rbp)
movl $1, -16(%rbp)
LBB2_1: ## =>This Inner Loop Header: Depth=1
movl -12(%rbp), %eax
cmpl -16(%rbp), %eax
jl LBB2_4
## BB#2: ## in Loop: Header=BB2_1 Depth=1
movl -20(%rbp), %eax
imull -8(%rbp), %eax
movl %eax, -20(%rbp)
## BB#3: ## in Loop: Header=BB2_1 Depth=1
movl -16(%rbp), %eax
addl $1, %eax
movl %eax, -16(%rbp)
jmp LBB2_1
LBB2_4:
movl -4(%rbp), %eax
popq %rbp
retq
As you can see, I have 4 remarkable addresses: -8(%rbp), -12(%rbp), -16(%rbp) and -20(%rbp). Given the order of declaration in the C code, and the order of initialisation, -8(%rbp) is base, -12(%rbp) is n, -16(%rbp) is i and -20(%rbp) is p.
LBB2_1 is your loop condition. The instructions for the check are
* move value of n in %eax
* is the value of %eax lower then the value of i, store the result in %eax
* if %eax says that it was lower, go to label LBB2_4 else continue to next instruction
The three instructions after BB#2 are you actual multiplication. The three instructions after BB#3 are your increment of i, which is followed by an unconditional jump to your loop condition at label LBB2_1.
The ending of the power function is to take whatever is in memory address -4(%rbp), tu put it in %eax, and then leave the function (reset stack pointer, put value in %eax to the proper variable in the previous stack frame).
In the code produced by my compiler, I don't see the same result as you do, as I get every time the last two columns equal to 0 (-4(%rbp) is never set to anything). Except when adding a call to another function foo, taking two integers as parameters, having two local integer variables (to ensure that my new stack frame will be the same size as the power function one). This function actually set the address -4(%rbp). When calling my function right before entering the loop, I effectively find the value from -4(%rbp) as set in my function foo returned in my function power.
As a colleague just told me, playing with undefined behaviour is dangerous as your compiler is allowed to treat it any way it likes. It could be summoning a demon for what it's worth.
In definitive, or TL;DR, this undefined behaviour is handle in some way by the compiler. Whether some value is moved from one local variable, defined or not, or nothing special is moved to the register %eax is up to the compiler. Anyway, whatever was hanging in there, got returned when retq is called.
I have a C function which allocated some memory to an array that is going to be filled with natural numbers up to a certain N.
Lets say,
N = 10;
array = calloc(N, sizeof(int));
I then call upon an assembly function that I have written, however I don't seem to be able to access the array fields. I manage to find the value of N which is located at 8(%ebp), and I have checked with GDB that it really equals to the N set in the C code.
However, when I try to access the first element in the array, and move it to, for example %esi, the value is not zero as it should be.
That I do by using the following code
movl 12(%ebp), %esi
EDIT; I do of course fill the array with natural numbers before calling the assembly function. I just did not want to type in the for loop here.
As I understands it, the parentheses de-refrences the first element of the array, and copies that to esi, however, esi contains only a huge negative number when I use info registers on a breakpoint set after this code in GDB.
So, How do I access arrays that is calloced beforehand, and passed into an assembly function? Is it not possible to derefrence, and copy that single element?
Here is the C function that calls upon the assembly function
int main(int argc, char *argv[]){
int n = 10;
int *array = calloc(n, sizeof(int));
int i, j;
// Populate array up to N
for(i = 0; i < n; i++){
array[i] = 2 + i;
}
printf("Array: %d \n", sizeof(array));
// Run sievs
sievs_assembly(n, array);
// print prime
print_prime(array, n);
// Free mem
free(array);
return EXIT_SUCCESS;
}
I dont want to post the assembly file as a whole, since it is a school project, and I'm not asking for help solving the assessment, only the specific problem. How to derefrence an array item.
The function prototype is
extern void sievs_assembly(int n, int *a);
I thought that since the pointer *a is an int array, and the first argument N is located at 8(%ebp), that the first array element would be 12(%ebp).
How do I actually get to the value if its not enough to just do movl 12(%ebp), %esi
When you do:
movl 12(%ebp), %esi
you have moved the memory adress of your array into %esi. The value of the first element is what this adress is pointing to. To get that you can use:
movl (%esi), %eax
This moves the first element into %eax. The brackets basicly mean "what %esi is pointing to". The size of an int is probably 4 bytes for you (you could check with 'sizeof(int)'). So to acces the next element you could use:
movl 4(%esi), %eax
Which moves the next element into %eax.
I've also made an example program which prints 2 values from an array. Note: I made it for windows.
.macro print str #macro name is 'print'. 1 argument: 'str'
pushl \str #argument names are escaped
call _printf
addl $4, %esp #pop the arguments
.endm
.macro printf str fs #can't overload macro names, so let's call this one 'printf'
pushl \str
pushl \fs #printing numbers requires a format srting
call _printf
addl $8, %esp
.endm
.text
.global _main
_main: #actual program, '_main' becomes 'WinMain#16'
pushl %ebp #push frame
movl %esp, %ebp
movl $array, %esi #Move array pointer to $esi.
#print what %esi is pointing to
printf (%esi), $fs
#print a newline
print $nl
#print what %esi+4 is pointing to. Since a long is 4 bytes
#The next element of the array is 4 bytes further than the first
printf 4(%esi), $fs
movl $0, %eax #move 0 to return register
leave #pop frame
ret #return
.data
fs: .string "%i" #Format string
nl: .string "\n" #New Line
array: #Some array
.long 1,2
This program prints the output:
1
2
Edit:
Since this got some attention, I thought I'd update the answer with some macros.
And explain the _ prefixes on c library calls and main; I'm compiling on windows with MinGW, which requires those prefixes to avoid getting undefined reference errors. On linux they're not needed.
For further documentation about macros and GAS see: using as
A little bit modificated. Compile it by gcc -m32 -g -o foo foo.s
.data
fs: .string "%i" #Format string
nl: .string "\n" #New Line
array: .long 1,2
.text
.global main
main:
pushl %ebp #push frame
movl %esp, %ebp
movl $array, %esi #Move array pointer to $esi.
pushl (%esi) #Push what %esi is pointing to
pushl $fs #push the format string
call printf #call printf
addl $8, %esp #pop the arguments
pushl $nl #print a new line
call printf
addl $4, %esp
pushl 4(%esi) #push what %esi+4 is pointing to. Since a long is 4 bytes
pushl $fs #The next element is 4 bytes further than the first
call printf
addl $8, %esp
pushl $nl #print a new line
call printf
addl $4, %esp
pushl $0
call exit
This question already has an answer here:
Regarding post increment
(1 answer)
Closed 9 years ago.
int demo()
{
static int i = 1;
return i++;
}
int main()
{
printf("%d %d %d\n", demo(), demo(), demo());
return 0;
}
output:-
3 2 1
During the first demo call, 1 is returned.
I have heard that when return statement is executed, then control passes to the calling function without any further execution of code in called function.
So my question is that in my code when 1 is returned in first call, Why its value is incremented?
In other words I want to know that after returning 1 , why ++ is executed?
int demo()
{
static int i = 1;
return i++;
}
int main()
{
printf("%d %d %d\n", demo1(), demo2(), demo3());
return 0;
}
The order of execution of demo_i() is language dependent .
Now, comes use of static keyword .
Static variables persist on the stack through the entire duration of the program , even after function ends and returns the value .
Due to this , 1st time : i=1
return 1 , increment to 2 .
2nd time : i=2
return 2 , increment to 3 .
3rd time : i=3
return 3 , increment to 4 .
Hope this helps !
Three points to keep in mind here:
static variables into functions persist through the entire duration of the program as soon as they're created for the first time
That variable returned also has the postfix ++ operator which means: "use the value (i.e. return it) and increment it AFTERWARDS": the incremented value is not returned.
That's why that variable has "memory" of what happened and gets incremented.
-> Why you're seeing "3 2 1" instead of "1 2 3"?
The order in which the parameters are evaluated is not known 'a priori' and it's up to the compiler decide it, see https://stackoverflow.com/a/12960263/1938163
If you really want to know how is it possible that the value gets first returned and then incremented, take a look at the generated asm code:
demo(): # #demo()
movl demo()::i, %eax # move i and put it into eax
movl %eax, %ecx # Move eax into ecx -> eax will be used/returned!
addl $1, %ecx # Increment ecx
movl %ecx, demo()::i # save ecx into i -> this is for the next round!
ret # returns!
main: # #main
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl $0, -4(%rbp)
callq demo() # Call demo()
movl %eax, -8(%rbp) # save eax in rbp-8 (contains 1, demo::i is 2 for the next round)
callq demo() # Call demo()
movl %eax, -12(%rbp) # save eax in rbp-12 (contains 2, demo::i is 3 for the next round)
callq demo() # Call demo()
leaq .L.str, %rdi # load str address
movl -8(%rbp), %esi # esi points to 1
movl -12(%rbp), %edx # edx points to 2
movl %eax, %ecx # move eax (3) into ecx (demo::i is 4 but doesn't get used)
movb $0, %al # needed by the ABI to call printf
callq printf # call printf() and display 3 2 1
movl $0, %ecx
movl %eax, -16(%rbp)
movl %ecx, %eax
addq $16, %rsp
popq %rbp
ret
demo()::i:
.L.str:
.asciz "%d %d %d\n"
The 64-bit ABI uses registers (RDI, RSI, RDX, RCX, R8 and R9) instead of the stack for argument passing.
[...] I want to know that after returning 1, why ++ is executed?
The postfix operator is defined by the C Standard to work like this:
6.5.2.4 Postfix increment and decrement operators
[...]
2 The result of the postfix ++ operator is the value of the operand. After the result is
obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate
type is added to it.)
So before the return is executed i is increment, but as the result of the postfix operation is the "original" value, return returns this "original" value.
Your function returns old value of i and increments it . Since you used static keyword the value of i is stored and available for next call (it is not vanished after the call).
I have heard that when return statement is executed, then control passes to the calling function without any further execution of code in called function.
You heard right. But it doesn't mean that the statement which is returned by return statement does not executed. See an example:
return a + b;
Now this statement executed then a+b get evaluated first and then its value is returned to the caller. In a similar way when
return i++;
get executed then i++ is executed. It returns the previous value of i and increment it by 1.
I got this short C Code.
#include <stdint.h>
uint64_t multiply(uint32_t x, uint32_t y) {
uint64_t res;
res = x*y;
return res;
}
int main() {
uint32_t a = 3, b = 5, z;
z = multiply(a,b);
return 0;
}
There is also an Assembler Code for the given C code above.
I don't understand everything of that assembler code. I commented each line and you will find my question in the comments for each line.
The Assembler Code is:
.text
multiply:
pushl %ebp // stores the stack frame of the calling function on the stack
movl %esp, %ebp // takes the current stack pointer and uses it as the frame for the called function
subl $16, %esp // it leaves room on the stack, but why 16Bytes. sizeof(res) = 8Bytes
movl 8(%ebp), %eax // I don't know quite what "8(%ebp) mean? It has to do something with res, because
imull 12(%ebp), %eax // here is the multiplication done. And again "12(%ebp).
movl %eax, -8(%ebp) // Now, we got a negative number in front of. How to interpret this?
movl $0, -4(%ebp) // here as well
movl -8(%ebp), %eax // and here again.
movl -4(%ebp), %edx // also here
leave
ret
main:
pushl %ebp // stores the stack frame of the calling function on the stack
movl %esp, %ebp // // takes the current stack pointer and uses it as the frame for the called function
andl $-8, %esp // what happens here and why?
subl $24, %esp // here, it leaves room for local variables, but why 24 bytes? a, b, c: the size of each of them is 4 Bytes. So 3*4 = 12
movl $3, 20(%esp) // 3 gets pushed on the stack
movl $5, 16(%esp) // 5 also get pushed on the stack
movl 16(%esp), %eax // what does 16(%esp) mean and what happened with z?
movl %eax, 4(%esp) // we got the here as well
movl 20(%esp), %eax // and also here
movl %eax, (%esp) // what does happen in this line?
call multiply // thats clear, the function multiply gets called
movl %eax, 12(%esp) // it looks like the same as two lines before, except it contains the number 12
movl $0, %eax // I suppose, this line is because of "return 0;"
leave
ret
Negative references relative to %ebp are for local variables on the stack.
movl 8(%ebp), %eax // I don't know quite what "8(%ebp) mean? It has to do something with res, because`
%eax = x
imull 12(%ebp), %eax // here is the multiplication done. And again "12(%ebp).
%eax = %eax * y
movl %eax, -8(%ebp) // Now, we got a negative number in front of. How to interpret this?
(u_int32_t)res = %eax // sets low 32 bits of res
movl $0, -4(%ebp) // here as well
clears upper 32 bits of res to extend 32-bit multiplication result to uint64_t
movl -8(%ebp), %eax // and here again.
movl -4(%ebp), %edx // also here
return ret; //64-bit results are returned as a pair of 32-bit registers %edx:%eax
As for the main, see x86 calling convention which may help making sense of what happens.
andl $-8, %esp // what happens here and why?
stack boundary is aligned by 8. I believe it's ABI requirement
subl $24, %esp // here, it leaves room for local variables, but why 24 bytes? a, b, c: the size of each of them is 4 Bytes. So 3*4 = 12
Multiples of 8 (probably due to alignment requirements)
movl $3, 20(%esp) // 3 gets pushed on the stack
a = 3
movl $5, 16(%esp) // 5 also get pushed on the stack
b = 5
movl 16(%esp), %eax // what does 16(%esp) mean and what happened with z?
%eax = b
z is at 12(%esp) and is not used yet.
movl %eax, 4(%esp) // we got the here as well
put b on the stack (second argument to multiply())
movl 20(%esp), %eax // and also here
%eax = a
movl %eax, (%esp) // what does happen in this line?
put a on the stack (first argument to multiply())
call multiply // thats clear, the function multiply gets called
multiply returns 64-bit result in %edx:%eax
movl %eax, 12(%esp) // it looks like the same as two lines before, except it contains the number 12
z = (uint32_t) multiply()
movl $0, %eax // I suppose, this line is because of "return 0;"
yup. return 0;
Arguments are pushed onto the stack when the function is called. Inside the function, the stack pointer at that time is saved as the base pointer. (You got that much already.) The base pointer is used as a fixed location from which to reference arguments (which are above it, hence the positive offsets) and local variables (which are below it, hence the negative offsets).
The advantage of using a base pointer is that it is stable throughout the entire function, even when the stack pointer changes (due to function calls and new scopes).
So 8(%ebp) is one argument, and 12(%ebp) is the other.
The code is likely using more space on the stack than it needs to, because it is using temporary variables that could be optimized out of you had optimization turned on.
You might find this helpful: http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames
I started typing this as a comment but it was getting too long to fit.
You can compile your example with -masm=intel so the assembly is more readable. Also, don't confuse the push and pop instructions with mov. push and pop always increments and decrements esp respectively before derefing the address whereas mov does not.
There are two ways to store values onto the stack. You can either push each item onto it one item at a time or you can allocate up-front the space required and then load each value onto the stackslot using mov + relative offset from either esp or ebp.
In your example, gcc chose the second method since that's usually faster because, unlike the first method, you're not constantly incrementing esp before saving the value onto the stack.
To address your other question in comment, x86 instruction set does not have a mov instruction for copying values from memory location a to another memory location b directly. It is not uncommon to see code like:
mov eax, [esp+16]
mov [esp+4], eax
mov eax, [esp+20]
mov [esp], eax
call multiply(unsigned int, unsigned int)
mov [esp+12], eax
Register eax is being used as an intermediate temporary variable to help copy data between the two stack locations. You can mentally translate the above as:
esp[4] = esp[16]; // argument 2
esp[0] = esp[20]; // argument 1
call multiply
esp[12] = eax; // eax has return value
Here's what the stack approximately looks like right before the call to multiply:
lower addr esp => uint32_t:a_copy = 3 <--. arg1 to 'multiply'
esp + 4 uint32_t:b_copy = 5 <--. arg2 to 'multiply'
^ esp + 8 ????
^ esp + 12 uint32_t:z = ? <--.
| esp + 16 uint32_t:b = 5 | local variables in 'main'
| esp + 20 uint32_t:a = 3 <--.
| ...
| ...
higher addr ebp previous frame