汇编语言快速入门学习笔记
程序計數(shù)器(PC)在x86-64中用%rip表示,其中給出了將要執(zhí)行的下一條指令在內(nèi)存中的地址
在Linux下查看匯編代碼的兩種方式:
- 對于一可執(zhí)行文件hello,使用objdump -d hello即可在控制臺打印其反匯編代碼
- 在編譯C代碼時,使用gcc的-S參數(shù)生成匯編代碼文件,可以用文本編輯器查看gcc -Og -S hello.c -o hello.s
所有以.開頭的行都是知道匯編器和鏈接器工作的偽指令,通常可以忽略。
AT&T與Intel匯編代碼格式:兩種格式在許多方面不同,在gcc/objdump工具中默認格式是AT&T,使用下面的命令可以讓GCC產(chǎn)生Intel格式的代碼:gcc -Og -S -masm=intel hello.c
操作數(shù)指示符:
其中,Imm表示立即數(shù)(immediate的縮寫);R[]數(shù)組為寄存器內(nèi)容數(shù)組,如R[r_a]即表示寄存器r_a中的值;M[]數(shù)組表示內(nèi)存內(nèi)容數(shù)組,如M[Imm]即表示內(nèi)存第Imm號單元中存放的數(shù)據(jù)。各個寄存器的大小如下:
數(shù)據(jù)傳送指令MOV類:包括movb, movw, movl, movq等指令,它們的區(qū)別在于操作數(shù)據(jù)的大小不同。
源操作數(shù)S指定的值是一個立即數(shù)(常數(shù)),存儲在寄存器或內(nèi)存中。目的操作數(shù)D指定一個位置,要么是一個寄存器,要么是一個內(nèi)存地址。x86-64限制傳送指令的兩個操作數(shù)S和D不能都指向內(nèi)存位置,兩個內(nèi)存位置間復制數(shù)據(jù)必須通過寄存器中轉(zhuǎn)。記住,MOV A B指令中,源操作數(shù)在前,目標操作數(shù)在后,是把A復制到B中!
注意:源操作數(shù)只有以$開頭的才是立即數(shù),其它的以%開頭的是表示寄存器中存放的數(shù)據(jù),有括號的表示內(nèi)存某一地址中的數(shù)據(jù)。目標操作數(shù)以%開頭的表示某一寄存器,是將源操作數(shù)復制到這個寄存器中(不是按寄存器中保存的數(shù)據(jù)在內(nèi)存中尋址);有括號的表示內(nèi)存的一地址,是將源操作數(shù)復制到內(nèi)存中這個地址對應的內(nèi)存單元當中。
movb, movw, movl, movq都要求源操作數(shù)和目標操作數(shù)表示的數(shù)據(jù)大小相同,還有其他指令如movzbw,movzbl,movzwl,movzbq,movzwq,movsbw,movsbl,movswl,movsbq,movswq,movslq,cltq,是將較小的源值復制到較大的目的時使用,其中涉及到高位擴展填充(零擴展/符號擴展),這里不再詳細解釋。值得注意的是,如果源操作數(shù)的數(shù)據(jù)大小小于目標操作數(shù)表示的數(shù)據(jù)大小,movb, movw, movl, movq指令只會修改源操作數(shù)對應的位,不會修改其他的位,唯一的例外是movl(這是由于x86-64的慣例原因,這里不解釋)。
棧操作
在x86-64機器中,棧是向低地址方向增長的,也就是說,棧底的地址值更大。%rsp寄存器專門用于存儲棧頂?shù)刂贰9手噶頿ushq %rbq等價于兩條指令subq $8,%rsp和movq %rbq,(%rsp),指令popq %rax等價于兩條指令movq (%rsp),%rax addq $8,%rsp。
算術(shù)運算
條件碼
CMP和TEST指令
訪問條件碼(SET指令)
跳轉(zhuǎn)指令
jmp跳轉(zhuǎn)指令分直接跳轉(zhuǎn)和簡介跳轉(zhuǎn),直接跳轉(zhuǎn)是給出一個標號作為跳轉(zhuǎn)目標,間接跳轉(zhuǎn)是"*"后跟一個操作數(shù)指示符(寄存器或內(nèi)存地址)。如 jmp *%rax用寄存器rax中的值作為跳轉(zhuǎn)目標, jmp *(%rax)以%rax中的值作為讀地址,從內(nèi)存中讀出跳轉(zhuǎn)目標。
條件傳送指令
8086中的寄存器:
(1) 8個通用寄存器:
數(shù)據(jù)寄存器
AX—Accumulator Register,累加寄存器
BX—Base Segment Register,基址寄存器
CX—Count Segment Register,計數(shù)寄存器
DX—Data Segment Register,數(shù)據(jù)寄存器字符串
地址指針寄存器
SI—Source Index Register,源變址寄存器
DI—Destination Index Register,目的變址寄存器
SP—Stack Pointer Register,堆棧寄存器
BP—Base Pointer Register,基址指針寄存器
(2) 6個段寄存器:
CS—Code Segment Register,代碼段寄存器
DS—Data Segment Register,數(shù)據(jù)段寄存器
SS—Stack Segment Register,堆棧段寄存器
FS—Flag Segment Register,標志段寄存器
FS寄存器指向當前活動線程的TEB結(jié)構(gòu)(線程結(jié)構(gòu))。
GS—Global Segment Register,全局段寄存器it
(3) 2個控制寄存器:
IP—Instruction Pointer,指令指針,即PC(Program counter),程序計數(shù)器。
PSW—Processor State Word,微處理器狀態(tài)字
即在8086中,%rip就是PC,%rsp為棧頂指針
轉(zhuǎn)移控制(call,ret指令)
call指令有一個目標,即指明被調(diào)用過程起始的指令地址。調(diào)用可以是直接的(call Label),也可以是間接的(call *Operand)。一個call指令相當于一條push指令接一條jmp指令,先將原過程中call指令的下一條指令的地址push到棧中,再跳轉(zhuǎn)到目標過程。而ret指令相當于一條pop指令接一條jmp指令,先從棧中彈出之前在棧中push的地址(即之前保存的"call的下一條指令的地址"),然后跳轉(zhuǎn)到這個地址,完成ret指令,繼續(xù)執(zhí)行原過程。
總結(jié)
以上是生活随笔為你收集整理的汇编语言快速入门学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux GCC用法
- 下一篇: [转]一篇很喜欢的知乎美文