实验4 汇编应用编程和c语言程序反汇编分析
一、实验目的
二、实验步骤
1、实验任务1
(1)使用文本编辑器,编写代码,具体如下:
assume cs:code data segment db 'welcome to masm!' data ends code segment start: mov ax,data mov es,ax mov ax,0b800h add ax,110 mov ds,ax mov cx,16 mov bx,0 mov si,0 s: mov al,es:[bx] mov [bx+si+64],al mov byte ptr [bx+si+64+1],2 mov [bx+si+64+160],al mov byte ptr [bx+si+64+160+1],100100b mov [bx+si+64+320],al mov byte ptr [bx+si+64+320+1],1110001b inc bx inc si loop s mov ax,4c00h int 21h code ends end start
(2)解释说明
- 首先在数据段 data 中,放入数据 db 'welcome to masm!' ,并将data段的段地址传给 es 寄存器。x
- 将 80×25 彩色字符模式下的第 0 行显存空间的地址传递给 ds 寄存器。因为一行的是 160 个字节 ,所以每偏移一行,段地址 ds 寄存器需要加 10(因为160 = 0A0H,所以段地址加 0AH = 10),因为需要偏移 11 行,所以需要加上 110 ,使得 ds 段寄存器指向窗口的第 11 行。
- 因为字符串长度是 16,所以设置 cx 寄存器的值为 16,让循环进行 16 次。
- 使用 bx 和 si 两个寄存器,因为在 data 数据段中字符串是单个字节存储的,而输出到显存中,需要中间空出来一个,来设置显示的颜色。取数据的时候用 bx ,输出的时候用 bx+si 。
- 先将字符读到 al寄存器中,在输出到相应的位置上,因为 al 寄存器是 8 位寄存器,所以读写都是单字节。再设置颜色,这里要设置单字节 “ byte ptr [ ] ” 。
- 因为字符串长度是 16,需要 32 字节,而一行是 160 字节,所以可以计算出,要使得字符串居中显示,需要偏移 64 个字节。
- 一行是 160 字节,输入下一行的内容,则需要偏移160 个字节。
- 颜色设置,根据 “ 闪烁 R(背景) G(背景) B(背景) 高亮 R(前景) G(前景) B(前景) ” 相应的设置即可。绿色是00000010B,绿底红字是00100100B,白底蓝字是01110001B。
(3)编译、链接、运行结果

2、实验任务2
(1)使用文本编辑器,编写代码,具体如下:
assume cs:code, ds:data data segment str db 'try', 0 data ends code segment start: mov ax, data mov ds, ax mov si, offset str mov al, 2 call printStr mov ah, 4ch int 21h printStr: push bx push cx push si push di mov bx, 0b800H mov es, bx mov di, 0 s: mov cl, [si] mov ch, 0 jcxz over mov ch, al mov es:[di], cx inc si add di, 2 jmp s over: pop di pop si pop cx pop bx ret code ends end start
(2)编译、链接、运行结果

(3)进行相应的修改,再运行结果
-
把 line3 改为: str db 'another try', 0
- 把 line12 改为:mov al, 4

(4)根据结果,回答问题:
- line19-22, line36-39,这组对称使用的push、pop,这样用的目的是:因为在子程序中需要使用这些寄存器,为了在程序使用 ret 命令返回后,寄存器中的值不变。所以需要,先将这些寄存器的值 push 到栈中,等子程序运行结束,再使用 pop 将原先的数值还原到寄存器中。
-
line30的功能是:将 cx 寄存器中的数值保存到 es:[di] 内存单元中。可以上问看出,cl 寄存器中存储是 data 段的段数据中 “str” ,ch 寄存器是 al 寄存器的数值,而es:[di] 内存单元就是 0b800:0 就是显存的位置。所以当前指令的作用就是将 data 段中的 “str” 数据,根据不同的颜色保存到显存中,显示到屏幕上。
3、实验任务3
(1)使用文本编辑器,编写代码,具体如下:
assume cs:code, ds:data data segment x dw 1984 str db 16 dup(0) data ends code segment start: mov ax, data mov ds, ax mov ax, x mov di, offset str call num2str mov ah, 4ch int 21h num2str: push ax push bx push cx push dx mov cx, 0 mov bl, 10 s1: div bl inc cx mov dl, ah push dx mov ah, 0 cmp al, 0 jne s1 s2: pop dx or dl, 30h mov [di], dl inc di loop s2 pop dx pop cx pop bx pop ax ret code ends end start
(2)编译、链接、运行,在 debug 环境下反汇编,运行到程序结束之前,查看 data 段的数据值。

从截图中可以看见,data 数据段中,成功的把转换后的数字字符串 '1984' 存放在 “str” 标号后面的单元。
(3)对task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来, 实现对转换后的字符串进行输出
assume cs:code, ds:data data segment x dw 1984 str db 16 dup(0) data ends code segment start: mov ax, data mov ds, ax mov ax, x mov di, offset str call num2str mov si,offset str mov al, 2 call printStr mov ah, 4ch int 21h num2str: push ax push bx push cx push dx mov cx, 0 mov bl, 10 s1: div bl inc cx mov dl, ah push dx mov ah, 0 cmp al, 0 jne s1 s2: pop dx or dl, 30h mov [di], dl inc di loop s2 pop dx pop cx pop bx pop ax ret printStr: push bx push cx push si push di mov bx, 0b800H mov es, bx mov di, 0 s: mov cl, [si] mov ch, 0 jcxz over mov ch, al mov es:[di], cx inc si add di, 2 jmp s over: pop di pop si pop cx pop bx ret code ends end start
(4)运行重新编写过后的程序,可以看到截图结果。并修改程序中 x 标号后面的数值,都可以看出,都能正确的显示出来。


4、实验任务4
(1)使用文本编辑器,编写代码,具体如下:
assume cs:code, ds:data data segment str db 80 dup(?) data ends code segment start: mov ax, data mov ds, ax mov si, 0 s1: mov ah, 1 int 21h mov [si], al cmp al, '#' je next inc si jmp s1 next: mov cx, si mov si, 0 s2: mov ah, 2 mov dl, [si] int 21h inc si loop s2 mov ah, 4ch int 21h code ends end start
(2)编译、链接、运行程序,输入字符串,“ 2020, bye# ”,查看结果

(3)根据运行的结果,和对软中断的理解,回答问题:
- line12-19实现的功能:读入一个字符,将它存到 data 数据段中。同时,将读入的字符和 ‘ # ’ 进行比较,如果是 ‘ # ’ 跳到 next 标号处向下运行,否则继续读入下一个字符。
- line21-27实现的功能:输出 data 数据段中的一个字符,循环字符串的数量次数。
5、实验任务5
(1)在visual studio集成环境中,编写一个简单的包含有函数调用的c程序。代码如下:
#include <stdio.h> int sum(int, int); int main() { int a = 2, b = 7, c; c = sum(a, b); return 0; } int sum(int x, int y) { return (x + y); }
(2)在line7, line13分别设置断点,在调试模式下,查看反汇编代码。




(3)观察发现
- 通过反汇编代码,可以发现,程序的参数传递都是通过寄存器来传递的
- 函数的返回值,也是通过寄存器返回的,比如图中的的 eax 寄存器
- 在多个参数传递时,vs2019编译器,是从左向右依次将参数压入栈中的


浙公网安备 33010602011771号