亲爱的朋友们,现在 AI 时代已经到来,我的项目维护虽然在继续,但是无法同步和大家分享知识,最近我已经注册了微信订阅号,希望看到的朋友互相通知一下: 微信公众号:编程悟道
图解汇编基础
-
macos --
内置 -
linux --
内置 -
Windows --
MinGWorlinux vm
- 指令
- 伪指令
- 标签
- 注释
clang -S -O2 hello.c -o hello.s
#或者:
gcc -S -O2 hello.c -o hello.s# // 用汇编器编译成目标文件 as hello.s -o hello.o # //链接成可执行文件 gcc hello.o -o hello # //运行程序 ./hello
函数调用
/*function-call1.c */ #include <stdio.h> int fun1(int a, int b){ int c = 10; return a+b+c; } int main(int argc, char *argv[]){ printf("fun1: %d\n", fun1(1,2)); return 0; }
生成的汇编代码,文档里有注释:
# function call
# text segment, pure code
.section __TEXT,__text,regular,pure_instructions
_fun1:
# prelude to the function call, setting the stack pointer
pushq %rbp # save the bottom address of the caller's stack frame
movq %rsp , %rbp # set the top address of the caller's stack frame to the bottom of this stack frame
subq 4ドル , %rsp # extension stack
movl 10ドル , -4(%rbp) # The variable c is assigned a value of 10, which can also be written as movl 10,ドル (%rsp)
# do addition
movl %edi , %eax # put the first parameter in %eax
addl %esi , %eax # add the second parameter to %eax, %eax is also the register that stores the return value
addl -4(%rbp), %eax # plus the value of c
addq 4ドル , %rsp # shrink the stack
# at the end of the function call, restore the stack pointer to its original value
pushq %rbp # save the bottom address of the caller's stack frame
movq %rsp , %rbp # set the top address of the caller's stack frame to the bottom of this stack frame
# set the first and second parameters, 1 and 2 respectively
movl 1,ドル %edi
movl 2,ドル %esi
callq _fun1 # call function
# set parameters for pritf
leaq L_.str(%rip), %rdi # the first parameter is the address of the string
movl %eax, %esi # the second parameter is the return value of the previous parameter
# set the return value. This sentence is also commonly used in commands such as xorl %esi, %esi, which are all set to zero
movl 0ドル , %eax
# restore the bottom value of the caller's stack frame
popq %rbp # restore the bottom value of the caller's stack frame
retq # return
# text segment, save string literal
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "Hello World! :%d \n"
.text
.globl _fun1
_fun1:
LFB0:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
movl %edi, -4(%rbp)
jmp L2
L3:
addl 1,ドル -4(%rbp)
L2:
cmpl 9,ドル -4(%rbp)
jle L3
nop
nop
popq %rbp
LCFI2:
ret
LFE0:
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set0,ドルLECIE1-LSCIE1
.long L$set0ドル
LSCIE1:
.long 0
.byte 0x1
.ascii "zR0円"
.byte 0x1
.byte 0x78
.byte 0x10
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x7
.byte 0x8
.byte 0x90
.byte 0x1
.align 3
LECIE1:
LSFDE1:
.set L$set1,ドルLEFDE1-LASFDE1
.long L$set1ドル
LASFDE1:
.long LASFDE1-EH_frame1
.quad LFB0-.
.set L$set2,ドルLFE0-LFB0
.quad L$set2ドル
.byte 0
.byte 0x4
.set L$set3,ドルLCFI0-LFB0
.long L$set3ドル
.byte 0xe
.byte 0x10
.byte 0x86
.byte 0x2
.byte 0x4
.set L$set4,ドルLCFI1-LCFI0
.long L$set4ドル
.byte 0xd
.byte 0x6
.byte 0x4
.set L$set5,ドルLCFI2-LCFI1
.long L$set5ドル
.byte 0xc
.byte 0x7
.byte 0x8
.align 3
LEFDE1:
.ident "GCC: (Homebrew GCC 9.3.0_1) 9.3.0"
.subsections_via_symbols
另一种写法:
.text
.globl _fun1
_fun1:
LFB0:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
movl %edi, -4(%rbp)
cmpl 10,ドル -4(%rbp)
jle L2
movl 4,ドル %eax
jmp L3
L2:
movl 8,ドル %eax
L3:
popq %rbp
LCFI2:
ret
LFE0:
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set0,ドルLECIE1-LSCIE1
.long L$set0ドル
LSCIE1:
.long 0
.byte 0x1
.ascii "zR0円"
.byte 0x1
.byte 0x78
.byte 0x10
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x7
.byte 0x8
.byte 0x90
.byte 0x1
.align 3
LECIE1:
LSFDE1:
.set L$set1,ドルLEFDE1-LASFDE1
.long L$set1ドル
LASFDE1:
.long LASFDE1-EH_frame1
.quad LFB0-.
.set L$set2,ドルLFE0-LFB0
.quad L$set2ドル
.byte 0
.byte 0x4
.set L$set3,ドルLCFI0-LFB0
.long L$set3ドル
.byte 0xe
.byte 0x10
.byte 0x86
.byte 0x2
.byte 0x4
.set L$set4,ドルLCFI1-LCFI0
.long L$set4ドル
.byte 0xd
.byte 0x6
.byte 0x4
.set L$set5,ドルLCFI2-LCFI1
.long L$set5ドル
.byte 0xc
.byte 0x7
.byte 0x8
.align 3
LEFDE1:
.ident "GCC: (Homebrew GCC 9.3.0_1) 9.3.0"
.subsections_via_symbols
.text
.p2align 4
.globl _fun1
_fun1:
LFB0:
addss %xmm1, %xmm0 #浮点数传参用XMM寄存器,加法用addss指令
addss lC0(%rip), %xmm0 #把常量2.0加到xmm0上,xmm0保存返回值
ret
LFE0:
.literal4
.align 2
lC0:
.long 1073741824
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set0,ドルLECIE1-LSCIE1
.long L$set0ドル
LSCIE1:
.long 0
.byte 0x1
.ascii "zR0円"
.byte 0x1
.byte 0x78
.byte 0x10
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x7
.byte 0x8
.byte 0x90
.byte 0x1
.align 3
LECIE1:
LSFDE1:
.set L$set1,ドルLEFDE1-LASFDE1
.long L$set1ドル
LASFDE1:
.long LASFDE1-EH_frame1
.quad LFB0-.
.set L$set2,ドルLFE0-LFB0
.quad L$set2ドル
.byte 0
.align 3
LEFDE1:
.ident "GCC: (Homebrew GCC 9.3.0_1) 9.3.0"
.subsections_via_symbols
C 函数传多个参数的代码:
#include <stdio.h> extern int fun1(int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8); int main(int argc, char *argv[]) { printf("fun1: %d \n", fun1(1,2,3,4,5,6,7,8)); return 0; }
将生成的汇编代码编译为目标文件,并结合链接器,生成可执行文件或库
# 生成链接文件 as convention-fun1.s -o convention-fun1.o # 生成可执行文件或库 gcc conv.c convention-fun1.o -o convention