at&a 64汇编
1.第一个at&a 64汇编
1 .section .data 2 strFormat: 3 .asciz "%s\n" 4 strUseLibc: 5 .asciz "Hi, If you see me, you called c lib :)" 6 strUseSyscall: 7 .asciz "And if you see me, you called syscall.\n" 8 endOfStrUseSyscall: 9 10 .section .text 11 .globl _start 12 _start: 13 # 函数调用的传参已经不再单纯使用压栈的方式 14 movq $strFormat, %rdi 15 movq $strUseLibc, %rsi 16 call printf 17 18 # 系统调用的寄存器已经改变,int 0x80 也被syscall 替代 19 movq $1, %rdi 20 movq $strUseSyscall, %rsi 21 movq $(endOfStrUseSyscall-strUseSyscall), %rdx 22 movq $1, %rax 23 syscall 24 25 #另外系统调用的编号也不同了 26 movq $127, %rdi # 故意返回一个非0 值 27 movq $60, %rax 28 syscall
2 从c 转成汇编,再编译成bin
GCC 编译的背后
http://tinylab.org/behind-the-gcc-compiler/
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int sum(int a) { 5 return a; 6 } 7 int main() { 8 int b = 0; 9 b = sum(1); 10 printf("hello:%d\n", b); 11 _exit(0); 12 }
1 gcc -S test.c -fno-asynchronous-unwind-tables -fno-exceptions -fno-stack-protector 2 sed -i -e "s#main#_start#g" test.s 3 gcc -c test.s 4 #ld -o test test.o /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2 5 ld -o test test.o -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2
gcc -S test.c
1 .file "test.c" 2 .text 3 .globl sum 4 .type sum, @function 5 sum: 6 .LFB0: 7 .cfi_startproc 8 pushq %rbp 9 .cfi_def_cfa_offset 16 10 .cfi_offset 6, -16 11 movq %rsp, %rbp 12 .cfi_def_cfa_register 6 13 movl %edi, -4(%rbp) 14 movl -4(%rbp), %eax 15 popq %rbp 16 .cfi_def_cfa 7, 8 17 ret 18 .cfi_endproc 19 .LFE0: 20 .size sum, .-sum 21 .section .rodata 22 .LC0: 23 .string "hello:%d\n" 24 .text 25 .globl main 26 .type main, @function 27 main: 28 .LFB1: 29 .cfi_startproc 30 pushq %rbp 31 .cfi_def_cfa_offset 16 32 .cfi_offset 6, -16 33 movq %rsp, %rbp 34 .cfi_def_cfa_register 6 35 subq $16, %rsp 36 movl $0, -4(%rbp) 37 movl $1, %edi 38 call sum 39 movl %eax, -4(%rbp) 40 movl -4(%rbp), %eax 41 movl %eax, %esi 42 movl $.LC0, %edi 43 movl $0, %eax 44 call printf 45 movl $0, %edi 46 call _exit 47 .cfi_endproc 48 .LFE1: 49 .size main, .-main 50 .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609" 51 .section .note.GNU-stack,"",@progbits
.cfi_startproc
.cfi_def_cfa_offset
.cfi_def_cfa_register
.cfi_def_cfa
.cfi_def_cfa
这些指令叫 cfi 指令,https://cloud.tencent.com/developer/ask/102663 具体用法先不用管。
c 可用 -fno-asynchronous-unwind-tables gcc选项去除,这样方便我们看代码
cpp 必须 -fno-asynchronous-unwind-tables -fno-exceptions 一起用才能去除
movq %fs:40, %rax
xorq %fs:40, %rdx
可用 -fno-stack-protector 去除
1 .file "test.c" 2 .text 3 .globl sum 4 .type sum, @function 5 sum: 6 pushq %rbp 7 movq %rsp, %rbp 8 movl %edi, -4(%rbp) 9 movl -4(%rbp), %eax 10 popq %rbp 11 ret 12 .size sum, .-sum 13 .section .rodata 14 .LC0: 15 .string "hello:%d\n" 16 .text 17 .globl main 18 .type main, @function 19 main: 20 pushq %rbp 21 movq %rsp, %rbp 22 subq $16, %rsp 23 movl $0, -4(%rbp) 24 movl $1, %edi 25 call sum 26 movl %eax, -4(%rbp) 27 movl -4(%rbp), %eax 28 movl %eax, %esi 29 movl $.LC0, %edi 30 movl $0, %eax 31 call printf 32 movl $0, %edi 33 call _exit 34 .size main, .-main 35 .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609" 36 .section .note.GNU-stack,"",@progbits
堆栈平衡
https://www.cnblogs.com/mysqlinternal/p/12737841.html
.rodata ro代表read only,即只读数据(const)。
字符串长度
msg: .string "Hello,world!\n"#要输出的字符串
len=. -msg #字串长度
用户自定义section
static int __attribute__((section(".xinit"))) hello() { printf("abc"); } 18 .section .xinit,"ax",@progbits 19 .type hello, @function 20 hello: 21 pushq %rbp 22 movq %rsp, %rbp 23 movl $.LC0, %edi 24 movl $0, %eax 25 call printf 26 nop 27 popq %rbp 28 ret 29 .size hello, .-hello
.section .xinit,"ax",@progbits
.section name [, "flags"[, @type[,flag_specific_arguments]]]
https://sourceware.org/binutils/docs/as/Section.html
http://web.mit.edu/rhel-doc/3/rhel-as-en-3/section.html
call printf 前有movl $0, %eax
https://stackoverflow.com/questions/6212665/why-is-eax-zeroed-before-a-call-to-printf