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