【C編程】彙編語言文件
C編程時,我們可能需要做一些彙編語言編程,以增加granularity。另外,在Xcode debug時,會跳入彙編語言程序。
彙編語言的程序結構如下。[1]
# PURPOSE:
# Simple program that exits and returns a
# status code back to the Linux kernel
# INPUT: none
# OUTPUT: returns a status code.This can be viewed by typing 'echo $'?
# after running the program
# VARIABLES:
# %eax holds the system call number
# %ebx holds the return status
#
#.section _data
#.section _text
.globl _start
_start:
movl $1, %eax # this is the linux kernel command
# number (system call) for exiting
# a program
movl $0, %ebx # this is the status number we will
# return to the operating system.
# Change this around and it will
# return different things to
# echo $?
int $0x80 # this wakes up the kernel to run
# the exit command
這是C exit(0)對應的彙編語言,eax存儲system call number,ebx存儲返回值。可用echo $?查看返回值。
以.開頭的叫偽指令或者彙編指示器,偽指令是為了指導彙編器,彙編器會處理這些指令,而不會直接被翻譯成機器代碼。比如,.section將程序分割成多個section。
#是彙編語言程序的註釋。
以上代碼存為exit.s。先經assembler編譯為.o文件,再經linker生成可執行程序。
我的機器是MacOS 10.14.5。本例我的實際操作是:
as exit.s -o exit.o
gcc exit.o -o exit
echo $?
使用彙編語言編譯器as編譯為.o文件。再用gcc將.o編譯為可執行程序。使用gcc而不是ld,是因為我嘗試了,不成功,有的程序可以ld成功。
每個機器不同的處理器,彙編語言不同。如何適應?
我想從C語言編譯的彙編文件學習。
比如hello.c程序:
#include <stdio.h>
int main() {
printf("您好,世界。");
return 0;
}
gcc -save-temps hello.c
gcc編譯依次經過1)預處理器(preprocessor)生成的.i文件;2)C編譯器,生成彙編語言程序.s文件;3)彙編編譯器,生成目標代碼.o文件,這是代碼;4)Linker,在操作系統註冊,生成可執行程序。-save-temps參數可讓我們看到過程文檔。[2]
打開hello.s。
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 10, 14 sdk_version 10, 15
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl $0, -4(%rbp)
leaq L_.str(%rip), %rdi
movb $0, %al
callq _printf
xorl %ecx, %ecx
movl %eax, -8(%rbp) ## 4-byte Spill
movl %ecx, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "\346\202\250\345\245\275\357\274\214\344\270\226\347\225\214\343\200\202"
.subsections_via_symbols
這裏exit部分看起來用到了eax,ecx。中文UTF8編碼用ASCII碼的八進制顯示,\346=3*64+4*8+6=230=\xe6, \202=\x82, \250=\xa8,每個中文字三個字節,在Terminal printf "\346\202\250"顯示『您』,printf "\xe6\x82\xa8"亦同。
另一個Hello World程序的代碼是這樣的:[3]
.global start
.intel_syntax noprefix
start:
# Write "Hello World"
mov rax, 0x2000004 # system call 4 (write code)
mov rdi, 1
lea rsi, hello_world[rip]
mov rdx, 12 # Set register rdx to 12
syscall # envoke syscall
# Exit program
mov rax, 0x2000001 # system call 1 (exit code)
mov rdi, 99 # set the exit code to 99
syscall
hello_world: # Definition of hello_world
.asciz "Hello World\n"
為什麼是rax,rdi?這些寄存器好像有包含和被包含、整體和部分的關係。但我也還不清楚。這機器編譯的.s文件難得多吧?其實我看不懂,我只是計劃這樣學習彙編語言。
這裏是彙編語言整體的命令查詢。[4]
參考:
Jason Note,如何在linux下編譯彙編程序,內功心法是彙編程序的結構,https://jasonblog.github.io/note/assembly/ru_he_zai_linux_xia_bian_yi_hui_bian_cheng_xu_ff0c.html ↩︎
Tiffany的世界,[GCC]GCC常用命令和参数,2025-07-08,https://zhuanlan.zhihu.com/p/1925840990817740428 ↩︎
Getting Started with Assembly on x86-64 MacOS: Hello World, https://zerodayarcade.com/tutorials/hello-world-assembly-macos ↩︎

浙公网安备 33010602011771号