匯編語言系列文章僅作為實(shí)驗(yàn)報(bào)告和匯編學(xué)習(xí)參考,不作為任何技術(shù)文章,還望大佬們勿噴。
1. 實(shí)驗(yàn)名稱
搭建匯編語言的開發(fā)環(huán)境,熟悉匯編程序開發(fā)的基本步驟,掌握基本的調(diào)試操作。
2. 實(shí)驗(yàn)要求
基于VISUAL STUDIO 平臺,結(jié)合MASM32的匯編器,構(gòu)建IA-32匯編語言的開發(fā)環(huán)境。
3. 實(shí)驗(yàn)內(nèi)容
- VC6平臺下的匯編語言開發(fā)環(huán)境搭建(使用MASM32的匯編器+VC6)
配置IDE環(huán)境:
– 在VC的tools/option/Directories頁面中添加Irvine32.inc等所在的目錄到include files中; 添加Irvine32.lib等所在的目錄到library files.
– 將masm32中的ml.exe和ml.err拷貝到VC的Microsoft Visual Studio\VC98\Bin目錄中
創(chuàng)建與配置project:
– 新建VC的win32 console類型空工程
– 創(chuàng)建一個(gè)asm后綴的文件,并把匯編代碼(教材第85頁addsub3.asm)輸入該文件中,然后將該asm文件添加到Source Files
– 選中asm文件,在project settings/Custom Build頁面中命令行加:
ml /c /coff /Fo(InputName).obj
(TargetDir)$(InputName).obj
– “Project setting”頁面的”link”選項(xiàng)卡中“object/library module ”中加入irvine32.lib
- 匯編與鏈接不帶輸出的加減法程序(即教材第85頁addsubTest.asm);
- 在程序最后加入調(diào)用DumpRegs過程的語句,以輸出各寄存器的值。
- 以單步執(zhí)行的方式調(diào)試該程序,查看每步結(jié)果,并解釋每步結(jié)果,并寫成注釋。(特別注意對標(biāo)志位的影響)
- (可選)嘗試修改程序。
- (可選)單步跟蹤課件中4.3.3節(jié)的程序“ptr應(yīng)用示例”,結(jié)合VC6的內(nèi)存查看功能(通過菜單view?debug windows?Memory調(diào)出內(nèi)存查看窗口)理解每步的執(zhí)行結(jié)果。(注意課件中只是大部分代碼,請補(bǔ)全頭文件以及程序退出宏。)
4. 實(shí)驗(yàn)步驟或源代碼、結(jié)果
1. 實(shí)驗(yàn)步驟
- 匯編與鏈接不帶輸出的加減法程序

- 在程序最后加入調(diào)用DumpRegs過程的語句,以輸出各寄存器的值

- 以單步執(zhí)行的方式調(diào)試該程序,查看每步結(jié)果,并解釋每步結(jié)果,并寫成注釋。

EIP指向下一條將要執(zhí)行指令的地址,即00401010所在的mov指令。

mov指令把1000h賦給ax寄存器,ax=1000h所以EAX變?yōu)榱?06E1000。

inc指令把a(bǔ)x加1,所以ax的地址從1000變成了1001。

dec指令把a(bǔ)x減1,所以ax的地址從1001變成了1000。

mov指令把SDWORD類型的Xval賦給eax,由于Xval的大小是26,16進(jìn)制下是1A,所以EAX為0000001A。

neg指令把EAX轉(zhuǎn)換成二進(jìn)制補(bǔ)碼,將操作數(shù)的符號取反,
00000000000000000000000000011010是正數(shù),二進(jìn)制補(bǔ)碼就是其本身,全部取反得再加1到11111111111111111111111111100110,即FFFFFFE6,十進(jìn)制為-26。

mov指令把SDWORD類型的Yval賦給ebx,由于Yval大小是30,30的16進(jìn)制就是1E,ebx的值為0000001E。

sub指令把ebx的值減去Zval的值,由于Zval是SDWORD,且大小是40,40的16進(jìn)制為28,Yval-Zval即0000001E+FFFFFFD8=FFFFFFF6,所以ebx的值為FFFFFFF6。

add指令把ebx的值加到eax上,F(xiàn)FFFFFF6+FFFFFFE6=FFFFFFDC,它的補(bǔ)碼的10進(jìn)制為-36,所以Rval的值就是ax的值,為DC。

mov指令把1賦給了cx,所以cx的值為0001,此時(shí)ZR=0。

sub指令cx的值減1,cx的值變?yōu)?000,此時(shí)零標(biāo)志位ZR=1。

mov指令把0FFFFh賦給ax,所以ax的值為FFFF。

inc指令把a(bǔ)x的值加1,即FFFF加上1,會進(jìn)位,得到0000。此時(shí)ZR=1。

move指令把0賦給cx,所以cx的值為0000,PL=0。

sub指令把cx的值加1,cx的值為0001,此時(shí)符號標(biāo)志位PL=1。

mov指令把7FFF賦給ax,所以ax的值為7FFF。

add指令把a(bǔ)x的值加2,ax的值變成8001,此時(shí)PL=1。

move指令把0FF賦給al,al的值為FF,ax的值為80FF,CY=0。

add指令把a(bǔ)l的值加1,al變成00,此時(shí)進(jìn)位,所以進(jìn)位標(biāo)識符CY=1。

move指令把+127賦給al,al的值變成7F,此時(shí)OV=0。

add指令把a(bǔ)l的值加1,al的值變成80,此時(shí)溢出,溢出標(biāo)志位OV=1。

move指令把-128賦給al,al的值變成80。

sub指令把a(bǔ)l的值減1,al的值變成7F,此時(shí)溢出,溢出標(biāo)志位OV=1。
2. 實(shí)驗(yàn)源代碼、結(jié)果
加上注釋后代碼是:
;加法和減法 (AddSubTest.asm)
include Irvine32.inc
.data
Rval SDWORD ?
Xval SDWORD 26
Yval SDWORD 30
Zval SDWORD 40
.code
main PROC
;INC和DEC
mov ax, 1000h ; ax = 1000h
inc ax ; ax = 1001h
dec ax ; ax = 1000h
; 表達(dá)式:Rval=-Xval+(Yval-Zval)
mov eax, Xval ; eax = 0000001a
neg eax ; -26
mov ebx, Yval
sub ebx, Zval ; -10
add eax, ebx ; -36
; 零標(biāo)志位示例
mov cx, 1 ; ZR = 0
sub cx, 1 ; ZR = 1
mov ax, 0FFFFh ;
inc ax ; ZR = 1
; 符號標(biāo)志位示例
mov cx, 0 ; PL = 0
sub cx, 1 ; PL = 1
mov ax, 7FFFh
add ax, 2 ; PL = 1
; 進(jìn)位標(biāo)志位示例
mov al, 0FFh ; CY = 0, AL = FF
add al, 1 ; CY = 1, AL = 00
; 溢出標(biāo)志位示例
mov al, +127 ; OV = 0
add al, 1 ; OV = 1
mov al, -128
sub al, 1 ; OV = 1
CALL DumpRegs
INVOKE ExitProcess, 0
main ENDP
END main
5. 實(shí)驗(yàn)結(jié)論和心得體會
- 再次加深了對通用寄存器和狀態(tài)標(biāo)志位的認(rèn)識;
- 建工程時(shí)一定要建windows console application,不然編譯時(shí)會報(bào)錯(cuò);
- 調(diào)試時(shí)要注意寄存器和標(biāo)志位,只要一步一步對應(yīng)著看,就能只能其工作的原理;
- 在寫匯編代碼時(shí),代碼段是必須有有的,報(bào)錯(cuò)時(shí)要讀懂報(bào)錯(cuò)緣由,注意解決報(bào)錯(cuò)原因;
- 對于一些常用的操作指令要牢記,并且要理解其內(nèi)容和作用。