This question already has answers here:
how does array[100] = {0} set the entire array to 0?
(4 answers)
Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets?
(2 answers)
Compiler using local variables without adjusting RSP
(1 answer)
Closed 2 years ago.
The following C function:
int main(void) {
char name[10] = "H";
}
Produces the following (unoptimized) assembly in Compiler Explorer:
main:
pushq %rbp
movq %rsp, %rbp
movq $72, -10(%rbp)
movw $0, -2(%rbp) <--------- ??
movl $0, %eax
popq %rbp
ret
What does the line above do? I would think we would want to null terminal the string by adding a $0 but I don't undertand why it's being added at -2. If helpful, here is a screenshot:
Related
This question already has answers here:
Why does the x86-64 / AMD64 System V ABI mandate a 16 byte stack alignment?
(1 answer)
Why does this function push RAX to the stack as the first operation?
(3 answers)
Closed 27 days ago.
In trying to learn more about how C generates assembly code, I was exploring the outputs of various snippets of C code using godbolt.
One peculiar thing I came across was encountered with this piece of code:
#include <stdio.h>
int main()
{
puts("Hello, world!\n");
return 0;
}
int x()
{
return 0;
}
Compiling with -O3 yielded the following assembly:
.LC0:
.string "Hello, world!\n"
main:
subq $8, %rsp
movl $.LC0, %edi
call puts
xorl %eax, %eax
addq $8, %rsp
ret
x:
xorl %eax, %eax
ret
My question is this:
Why does C allocate 8 bytes (subq $8, %rsp) on the stack before calling puts, which it doesn't end up using. Is this required to call puts? Or is it for moving the const into memory (which I don't think is right, as the constant is already defined, and the register is already axiomatically allocated).
So, what is the purpose of the subq $8, %rsp line here?
I included the int x function as well, to show that it does not allocate this when not calling puts?
This question already has answers here:
When should -m32 option of gcc be used?
(2 answers)
C to assembly call convention 32bit vs 64bit
(1 answer)
Closed 1 year ago.
I study on a tutorial and there is a c code like that
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
function(1,2,3);
}
He says after compile this code using gcc with -S switch we will get an assembly result like that
pushl $3
pushl $2
pushl $1
call function
However when I compile it my main part looks like
main:
.LFB1:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $3, %edx
movl $2, %esi
movl $1, %edi
call function
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
Are both meaning the same or am I doing wrong with somewhere?
This question already has answers here:
Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?
(1 answer)
How many bytes does the push instruction push onto the stack when I don't specify the operand size?
(2 answers)
Does each PUSH instruction push a multiple of 8 bytes on x64?
(2 answers)
What's the difference between 'push' and 'pushq' in at&t assembly
(1 answer)
How to determine the appropriate MOV instruction suffix based on the operands?
(1 answer)
Closed 2 years ago.
I've written the following basic C program:
int main() {
char a = 1;
char b = 5;
return a + b;
}
And it compiles in godbolt as:
main:
pushq %rbp
movq %rsp, %rbp
movb $1, -1(%rbp)
movb $5, -2(%rbp)
movsbl -1(%rbp), %edx
movsbl -2(%rbp), %eax
addl %edx, %eax
popq %rbp
ret
I have a few questions about the compiled asm:
Is movb used for 1byte (char), movw for 2byte (short), movl for 4byte (int), and movq for 8byte (int) integers? What then is just mov used for, without an extension?
Why is an offset used for movb $1 -1(%rbp), movb $5 -2(%rbp)? Why aren't the two numbers just moved into two different registers? For example, there's an addl %edx, %eax later on...why aren't the two numbers just moved into those two registers?
Why is movsbl used here? Why aren't the numbers just moved directly into the registers?
Is pushq / popq pushing/popping an 8byte pointer onto the stack? If so, what's the point of the movq %rsp, %rbp?
This question already has answers here:
Function Prologue and Epilogue in C
(4 answers)
Closed 3 years ago.
Take the following 5-line file I have:
#include <stdio.h>
int main() {
printf("Hello");
return 0;
}
It corresponds to the following assembly:
`main:
0x100000f60 <+0>: pushq %rbp
0x100000f61 <+1>: movq %rsp, %rbp
0x100000f64 <+4>: subq $0x10, %rsp
0x100000f68 <+8>: movl $0x0, -0x4(%rbp)
-> 0x100000f6f <+15>: leaq 0x34(%rip), %rdi ; "Hello"
We can notice the first line in main which prints "Hello" corresponds to the fifth instruction. What are the four preceding instructions: what do they do?
0x100000f60 <+0>: pushq %rbp
Push the caller's base pointer.
0x100000f61 <+1>: movq %rsp, %rbp
Copy the stack pointer into the base pointer (set up this function's stack frame)
0x100000f64 <+4>: subq $0x10, %rsp
Reserve stack space (presumably for the return value - you probably didn't compile this program with any optimizations enabled)
0x100000f68 <+8>: movl $0x0, -0x4(%rbp)
Put the return value (zero) on the stack.
-> 0x100000f6f <+15>: leaq 0x34(%rip), %rdi ; "Hello"
Load a pointer to the "Hello" string literal into rdi register.
This question already has an answer here:
Printing floating point numbers from x86-64 seems to require %rbp to be saved
(1 answer)
Closed 5 years ago.
I am attempting to test passing a floating point value to a C function from assembly on 64-bit Linux. The C file containing my C function looks like this:
#include <stdio.h>
extern void printer(double k){
printf("%f\n",k);
}
Its expected behavior is to simply print the floating point number passed to it. I am trying to accomplish this from an AT&T-syntax assembly file. If I am not mistaken, in 64-bit linux, the calling convention is to pass floating point arguments on the XMM registers. My .s file is the following:
.extern printer
.data
var:
.double 120.1
.global main
main:
movups (var),%xmm0
call printer
mov $60,%rax
syscall
What I'm hoping this could do is have a variable (var) with value 120.1. This is then moved to the xmm0 register, which I expect is what is used to pass the argument k. This understanding of the calling convention is also backed up by the assembly code generated from the C file, a portion of which is below:
printer:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movsd %xmm0, -8(%rbp)
movq -8(%rbp), %rax
movq %rax, -16(%rbp)
movsd -16(%rbp), %xmm0
movl $.LC0, %edi
movl $1, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
My .s file assembles to an executable, but running it only gives a segmentation fault, and doesn't print the floating point value. I can only assume this is because I'm not properly moving the value to xmm0 and/or using the register to pass it to the function. Can somebody explain how I should pass the value to the function?
You have defined main in the data section, which makes it non-executable. Add a .text directive before main.