Example: Call the addone function written in assembly language in the main function of C, add one of the input parameters, and return the result.
In the Assembly, register pressure stack should be used first, and the function can be called in other files using the Global Command. By the way, the static function in C can only be available in this file, that is, the compiled Assembly file does not use the global command, and the returned value of the Assembly is placed in the eax register.
The Assembly file name is addone. ASM. The assembly method is followed by the following content:
global addone;addone:MOV RAX, [RSP + 20]; stack top + 20 bytesADD RAX, 1RET
The input parameter is at least 20 bytes at the top of the stack. I don't know why it is 20. It is shown in the compiled assembly of C. The file name of C is calladdone. c. The content is as follows:
#include <stdio.h>int main(){ int a = 3; // printf("before call, a is %d.\n", a); a = addone(a); //printf("after call, a is %d.\n", a); return 0;}
The compiled C file is as follows:
.file"calladdone.c".text.globlmain.typemain, @functionmain:.LFB0:.cfi_startprocpushq%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq%rsp, %rbp.cfi_def_cfa_register 6subq$16, %rspmovl$3, -4(%rbp)movl-4(%rbp), %eaxmovl%eax, %edimovl$0, %eaxcalladdonemovl%eax, -4(%rbp)movl$0, %eaxleave.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.sizemain, .-main.ident"GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1".section.note.GNU-stack,"",@progbits
Two sentences in the middle:
Subq
$16, % RSP
Movl $3,-4 (% RBP)
Stack top to low address growth of 16 bytes, and put a = 3 in-4 ($ RBP), that is, stack top to bottom 12, and then call addone, that is:
Call
Addone
A return address will be pushed to the stack, Which is 64-bit on my machine, so it is 8 bytes. Now parameter A is at the top of the stack and at the bottom of the stack. (PS: I don't know if the 16 is as agreed by GCC ...)
Compile the ASM file:
nasm -felf64 addone.asm
The assembler I use is NASM, And the 64-bit machine is-felf64, and the 32-bit machine assembly option is-felf, followed by the file name. You can add the-G option to the debugging information.
After compilation, an addone. o file is generated, which is the object file. Then compile the file with the c file:
gcc calladdone.c addone.o
If GCC does not have the-O option, the. out file is generated by default. when running the file in GDB and adding a breakpoint, we can see that the value of a is indeed added with 1. Remove the comments from the above C file and output them as follows:
Before call, A is 3.
After call, A is 4.
Everything works.
Finally, paste how to use X in GDB to view registers and stacks. In GDB, directly help X to see the following:
Examine memory: X/FMT address.
Address is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are O (octal), x (HEX), D (decimal), u (unsigned decimal ),
T (Binary), F (float), A (address), I (Instruction), C (char) and S (string ).
Size letters are B (byte), H (halfword), w (Word), g (giant, 8 bytes ).
The specified number of objects of the specified size are printed
According to the format.
Defaults for format and size letters are those previusly used.
Default count is 1. Default address is following last thing printed
With this command or "print ".
For example, you can view 20 words (Word) at the top of the stack: X/20 W $ RSP
You can use X/10B $ RSP to view the top-down 10 bytes (byte) of the stack.