I have main function in C that runs code in assembly. I just want to make simple sum:
main.c
#include <stdio.h>
extern int addByAssembly(int first_number, int second_number);
int main (int argc, char **argv)
{
int sum=0;
sum = addByAssembly(5,4);
printf ("%d\n",sum);
return 0;
}
addByAssembly.s
.data
SYSREAD = 0
SYSWRITE = 1
SYSEXIT = 60
STDOUT = 1
STDIN = 0
EXIT_SUCCESS = 0
.text
#.global main
#main:
#call write
#movq $SYSEXIT, %rax
#movq $EXIT_SUCCESS, %rdi
#syscall
#********
.globl addByAssembly
addByAssembly:
pushq %rbp
movq %rsp, %rbp
movq 16(%rsp), %rax
addq 24(%rsp), %rax
movq %rbp, %rsp
popq %rbp
But i got mess in my sum. It looks like i badly pass arguments, beause if I do this:
movq $123, %rax
return value is 123. I 've tried many ways, but cannot find how to make this properly to sum.
Thanks 'Jester' for so much effort and time to get me this explained!
To sum up. Passing parameters from C to As ( and as well from As to C) has its own ABI convention.
As you can see there, params are send on order:
1) rdi
2) rsi
3) rdx
... and so on...
In case you have more parameters than in convention, it will be pushed to stack.
So in my case:
.globl addByAssembly
addByAssembly:
pushq %rbp
movq %rsp, %rbp
--movq 16(%rsp), %rax #this was wrong as my params are
--addq 24(%rsp), %rax # first in %rdi, second in %rsi
++lea (%rdi, %rsi), %rax # in my case this line will do
# %rdi+%rsi -> %rax (learn lea, usefull command)
# REMEMBER return value is always in %rax!
movq %rbp, %rsp
popq %rbp
Related
I have the C code:
long fib(long n) {
if (n < 2) return 1;
return fib(n-1) + fib(n-2);
}
int main(int argc, char** argv) {
return 0;
}
which I compiled by running gcc -O0 -fno-optimize-sibling-calls -S file.c yielding assembly code that has not been optimized:
.file "long.c"
.text
.globl fib
.type fib, #function
fib:
.LFB5:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $24, %rsp
.cfi_offset 3, -24
movq %rdi, -24(%rbp)
cmpq $1, -24(%rbp)
jg .L2
movl $1, %eax
jmp .L3
.L2:
movq -24(%rbp), %rax
subq $1, %rax
movq %rax, %rdi
call fib
movq %rax, %rbx
movq -24(%rbp), %rax
subq $2, %rax
movq %rax, %rdi
call fib
addq %rbx, %rax
.L3:
addq $24, %rsp
popq %rbx
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE5:
.size fib, .-fib
.globl main
.type main, #function
main:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size main, .-main
.ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
.section .note.GNU-stack,"",#progbits
My question is:
Why do we decrement the stack pointer by 24, subq $24, %rsp? As I see it, we store one element only, first argument n in %rdi, on the stack after the initial two pushes. So why don't we just decrement the stack pointer by 8 and then move n to -8(%rbp)? So
subq $8, %rsp
movq %rdi, -8(%rbp)
GCC does not fully optimize with -O0, not even its stack use. (This may aid in debugging by making some of its use of the stack more transparent to humans. For example, objects a, b, and c may share a single stack location if their active lifetimes (defined by uses in the program, not by the model of lifetime in the C standard) with -O3, but may have separately reserved places in the stack with -O0, and that makes it easier for a human to see where a, b, and c are used in the assembly code. The wasted 16 bytes may be a side effect of this, as those spaces may be reserved for some purpose that this small function did not happen to use, such as space to save certain registers if needed.)
Changing optimization to -O3 results in GCC subtracting only eight from the stack pointer.
I'm experimenting disassembling clang binaries of simple C programs (compiled with -O0), and I'm confused about a certain instruction that gets generated.
Here are two empty main functions with standard arguments, one of which returns value and other does not:
// return_void.c
void main(int argc, char** argv)
{
}
// return_0.c
int main(int argc, char** argv)
{
return 0;
}
Now, when I disassemble their assemblies, they look reasonably different, but there's one line that I don't understand:
return_void.bin:
(__TEXT,__text) section
_main:
0000000000000000 pushq %rbp
0000000000000001 movq %rsp, %rbp
0000000000000004 movl %edi, -0x4(%rbp)
0000000000000007 movq %rsi, -0x10(%rbp)
000000000000000b popq %rbp
000000000000000c retq
return_0.bin:
(__TEXT,__text) section
_main:
0000000100000f80 pushq %rbp
0000000100000f81 movq %rsp, %rbp
0000000100000f84 xorl %eax, %eax # We return with EAX, so we clean it to return 0
0000000100000f86 movl $0x0, -0x4(%rbp) # What does this mean?
0000000100000f8d movl %edi, -0x8(%rbp)
0000000100000f90 movq %rsi, -0x10(%rbp)
0000000100000f94 popq %rbp
0000000100000f95 retq
It only gets generated when I use the function is not void, so I thought that it might be another way to return 0, but when I changed the returned constant, this line didn't change at all:
// return_1.c
int main(int argc, char** argv)
{
return 1;
}
empty_return_1.bin:
(__TEXT,__text) section
_main:
0000000100000f80 pushq %rbp
0000000100000f81 movq %rsp, %rbp
0000000100000f84 movl $0x1, %eax # Return value modified
0000000100000f89 movl $0x0, -0x4(%rbp) # This value is not modified
0000000100000f90 movl %edi, -0x8(%rbp)
0000000100000f93 movq %rsi, -0x10(%rbp)
0000000100000f97 popq %rbp
0000000100000f98 retq
Why is this line getting generated and what is it's purpose?
The purpose of that area is revealed by the following code
int main(int argc, char** argv)
{
if (rand() == 42)
return 1;
printf("Helo World!\n");
return 0;
}
At the start it does
movl $0, -4(%rbp)
then the early return looks as follows
callq rand
cmpl $42, %eax
jne .LBB0_2
movl $1, -4(%rbp)
jmp .LBB0_3
and then at the end it does
.LBB0_3:
movl -4(%rbp), %eax
addq $32, %rsp
popq %rbp
retq
So, this area is indeed reserved to store the function return value. It doesn't appear to be terribly necessary and it is not used in optimized code, but in -O0 mode that's the way it works.
clang is making space on the stack for the arguments (registers edi and rsi) and puts the value 0 on the stack, too, for some reason. I assume that clang compiles your code to an SSA-representation like this:
int main(int argc, char** argv)
{
int a;
a = 0;
return a;
}
This would explain why a stack slot is allocated. If clang does constant propagation, too, this would explain why eax is zeroed out instead of being loaded from -4(%rbp). In general, don't think too much about dubious constructs in unoptimized assembly. After all, you forbade the compiler from removing useless code.
movl $0x0,-0x4(%rbp)
This instruction stores 0 at %rbp - 4. It seems that clang allocates a hidden local variable for an implicit return value from main.
From the clang mailing list:
Yes. We allocate an implicit local variable to hold the return value;
return statements then just initialize the return slot and jump to the
epilogue, where the slot is loaded and returned. We don't use a phi
because the control flow for getting to the epilogue is not
necessarily as simple as a simple branch, due to cleanups in local
scopes (like C++ destructors).
Implicit return values like main's are handled with an implicit store
in the prologue.
Source: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-February/019767.html
According the the standard (for hosted environments), 5.1.2.2.1, main is required to returrn an int result. So do not expect defined behavior if violating this.
Furthermore, main is actually _not required to explicitly return 0; this is implicitly returned if it reaches the end of the function. (Note this is only for main, which also does not have a prototype.
I'm having trouble figuring out how to use printf correctly in this function. So the function is called multInts and is supposed to multiply the first element of the first array with the first element of the second array and continue through the whole array. However, the lab instructions specify that I can't call printf in the main function. So, I need to print out the word "Products:\n" and then in each new line after that, print out the product. I don't know how to use printf within the loop, however. The instructor said that we should "call printf in the loop after calculating product" and also to "save and restore caller-save registers before calling printf," but I'm not sure what that means.
Here's what my code looks like so far:
.file "lab4.s"
.section .rodata
.LC0:
.string "Products: \n"
.LC1:
.string "%i \n"
.data
sizeIntArrays:
.long 5
sizeShortArrays:
.word 4
intArray1:
.long 10
.long 25
.long 33
.long 48
.long 52
intArray2:
.long 20
.long -37
.long 42
.long -61
.long -10
##### MAIN FUNCTION
.text
.globl main
.type main,#function
main:
pushq %rbp
movq %rsp, %rbp
#pass parameters and call other functions
movl sizeIntArrays, %edi #move size to registers for 1st parameter
leaq intArray1, %rsi #load effective address of intArray1 to register rsi
leaq intArray2, %rdx #load effective address of intArray2 to register rdx
call multInts #call multInts function
movq $0, %rax #return 0 to caller
movq %rbp, %rsp
popq %rbp
ret
.size main,.-main
##### MULTINTS
.globl multInts
.type multInts,#function
multInts:
pushq %rbp
movq %rsp, %rbp
#add code here for what the functions should do
movq $0, %r8 #initialize index for array access in caller save reg
movq $0, %rcx #initialize 8 byte caller save result reg
loop0:
cmpl %r8d, %edi #compare index to size
je exit0 #exit if equal
movslq (%rsi,%r8,4),%rax # Load a long into RAX
movslq (%rdx,%r8,4),%r11 # Load a long into R11
imulq %r11, %rax # RAX *= R11
addq %rax, %rcx # RCX += RAX
incq %r8 #increment index
jmp loop0
exit0:
movq $.LC0, %rdi
movq %rcx, %rsi
movq $0, %rax
call printf
movq %rbp, %rsp
popq %rbp
ret
.size multInts,.-multInts
What I've tried to do is just move the printf instruction to before the loop, but it gives me a segmentation fault when trying to run the loop because %rdi and %rsi contain the addresses of the arrays that need to be used in the loop. How do I get around that and which registers should I use? Also, how do I call printf within the loop?
The output should look something like this:
Products:
200
-925
1386
-2928
-520
Assume that printf clobbers all the call-clobbered registers (What registers are preserved through a linux x86-64 function call), and use different ones for anything that needs to survive from one iteration of the loop to the next.
Look at compiler output for an example: write a version of your loop in C and compile it with -Og.
Obviously you need to move the instructions that set up the args in registers
(like the format string) along with the call printf.
The easiest way to protect a register from being accessed by a subroutine is to push it. According to the ABI V calling convention printf may change any register except RBX, RBP, R12–R15. The registers you need to preserve are RAX, RDX, RSI, RDI, R8 and R11 (RCX is no longer needed), so push before the call to printf and pop them afterwards:
pushq %rax
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r11
movq $.LC1, %rdi
movq %rax, %rsi
movq $0, %rax
call printf
popq %r11
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rax
Now, you can copy the block into the loop. For each printf, you have to think about what needs to be secured:
...
multInts:
pushq %rbp
movq %rsp, %rbp
#add code here for what the functions should do
pushq %rdx # Preserve registers
pushq %rdi
pushq %rsi
movq $.LC0, %rdi # Format string (no further values)
movq $0, %rax # No vector registers used
call printf # Call C function
popq %rsi # Restore registers
popq %rdi
popq %rdx
movq $0, %r8 #initialize index for array access in caller save reg
loop0:
cmpl %r8d, %edi #compare index to size
je exit0 #exit if equal
movslq (%rsi,%r8,4),%rax # Load a long into RAX
movslq (%rdx,%r8,4),%r11 # Load a long into R11
imulq %r11, %rax # RAX *= R11
pushq %rax # Preserve registers
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r11
movq $.LC1, %rdi # Format string
movq %rax, %rsi # Value
movq $0, %rax # No vector registers used
call printf # Call C function
popq %r11 # Restore registers
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rax
incq %r8 #increment index
jmp loop0
exit0:
movq %rbp, %rsp
popq %rbp
ret
...
BTW: .string "%i \n" will force printf only to process the lower 32-bit of RDI. Use .string %lli \n instead.
I am trying to understand assembly code. I am stuck in the portion where the pointer is assigned and the code after leaq command
This is my C code:
#include <stdio.h>
#include<stdlib.h>
int main(){
int x=50;
int *y=&x;
return 0;
}
This is my corresponding ASSEMBLY code:
.file "AssemlyCode.c"
.def __main; .scl 2; .type 32; .endef
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $48, %rsp
.seh_stackalloc 48
.seh_endprologue
call __main
movl $50, -12(%rbp)
leaq -12(%rbp), %rax
movq %rax, -8(%rbp)
movl $0, %eax
addq $48, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (GNU) 5.4.0"
leaq -8(%rbp), %rax
movl %eax, -4(%rbp)
movl $0, %eax
addq $48, %rsp
popq %rbp
ret
leaq saves address of variable x on the stack to register rax. Variable x is automatic variable on the stack, hence it address is calculated as offset from register that holds stack frame pointer(rbp).
movl eax to stack saves argc argument to the stack.
next step is to put return value in eax register from main function(return 0)
two next opcodes are function epilogue - you are cleaning up used stack and restore previous frame pointer register.
and the last one instruction is simple return.
I'm experimenting disassembling clang binaries of simple C programs (compiled with -O0), and I'm confused about a certain instruction that gets generated.
Here are two empty main functions with standard arguments, one of which returns value and other does not:
// return_void.c
void main(int argc, char** argv)
{
}
// return_0.c
int main(int argc, char** argv)
{
return 0;
}
Now, when I disassemble their assemblies, they look reasonably different, but there's one line that I don't understand:
return_void.bin:
(__TEXT,__text) section
_main:
0000000000000000 pushq %rbp
0000000000000001 movq %rsp, %rbp
0000000000000004 movl %edi, -0x4(%rbp)
0000000000000007 movq %rsi, -0x10(%rbp)
000000000000000b popq %rbp
000000000000000c retq
return_0.bin:
(__TEXT,__text) section
_main:
0000000100000f80 pushq %rbp
0000000100000f81 movq %rsp, %rbp
0000000100000f84 xorl %eax, %eax # We return with EAX, so we clean it to return 0
0000000100000f86 movl $0x0, -0x4(%rbp) # What does this mean?
0000000100000f8d movl %edi, -0x8(%rbp)
0000000100000f90 movq %rsi, -0x10(%rbp)
0000000100000f94 popq %rbp
0000000100000f95 retq
It only gets generated when I use the function is not void, so I thought that it might be another way to return 0, but when I changed the returned constant, this line didn't change at all:
// return_1.c
int main(int argc, char** argv)
{
return 1;
}
empty_return_1.bin:
(__TEXT,__text) section
_main:
0000000100000f80 pushq %rbp
0000000100000f81 movq %rsp, %rbp
0000000100000f84 movl $0x1, %eax # Return value modified
0000000100000f89 movl $0x0, -0x4(%rbp) # This value is not modified
0000000100000f90 movl %edi, -0x8(%rbp)
0000000100000f93 movq %rsi, -0x10(%rbp)
0000000100000f97 popq %rbp
0000000100000f98 retq
Why is this line getting generated and what is it's purpose?
The purpose of that area is revealed by the following code
int main(int argc, char** argv)
{
if (rand() == 42)
return 1;
printf("Helo World!\n");
return 0;
}
At the start it does
movl $0, -4(%rbp)
then the early return looks as follows
callq rand
cmpl $42, %eax
jne .LBB0_2
movl $1, -4(%rbp)
jmp .LBB0_3
and then at the end it does
.LBB0_3:
movl -4(%rbp), %eax
addq $32, %rsp
popq %rbp
retq
So, this area is indeed reserved to store the function return value. It doesn't appear to be terribly necessary and it is not used in optimized code, but in -O0 mode that's the way it works.
clang is making space on the stack for the arguments (registers edi and rsi) and puts the value 0 on the stack, too, for some reason. I assume that clang compiles your code to an SSA-representation like this:
int main(int argc, char** argv)
{
int a;
a = 0;
return a;
}
This would explain why a stack slot is allocated. If clang does constant propagation, too, this would explain why eax is zeroed out instead of being loaded from -4(%rbp). In general, don't think too much about dubious constructs in unoptimized assembly. After all, you forbade the compiler from removing useless code.
movl $0x0,-0x4(%rbp)
This instruction stores 0 at %rbp - 4. It seems that clang allocates a hidden local variable for an implicit return value from main.
From the clang mailing list:
Yes. We allocate an implicit local variable to hold the return value;
return statements then just initialize the return slot and jump to the
epilogue, where the slot is loaded and returned. We don't use a phi
because the control flow for getting to the epilogue is not
necessarily as simple as a simple branch, due to cleanups in local
scopes (like C++ destructors).
Implicit return values like main's are handled with an implicit store
in the prologue.
Source: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-February/019767.html
According the the standard (for hosted environments), 5.1.2.2.1, main is required to returrn an int result. So do not expect defined behavior if violating this.
Furthermore, main is actually _not required to explicitly return 0; this is implicitly returned if it reaches the end of the function. (Note this is only for main, which also does not have a prototype.