实验4 汇编应用编程和c语言程序反汇编分析
实验内容
实验任务 1
在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串‘welcome to masm!’。
task1.asm:
assume cs:code, ds:data, ss:stack
data segment
db 'Welcome to masm!' ;16个字节
db 02H, 0A4H, 71H, 0, 0, 0, 0, 0 ;8个字节
dw 1824, 1984, 2144, 0, 0, 0, 0, 0 ;8个字
data ends
stack segment
dw 0, 0, 0, 0, 0, 0, 0, 0 ;用于存放cx
stack ends
code segment
start:
mov ax, data ;数据段
mov ds, ax
mov ax, stack ;栈
mov ss, ax
mov sp, 16
mov ax, 0B800H ;显存
mov es, ax
mov cx, 3 ;s0 运行三次,共 3 行
mov bx, 16 ;data 中颜色段起始地址
mov di, 24 ;data 中地址段存储地址
s0: push cx ;用栈暂存外部 cx
mov cx, 16 ;16 个字母
mov bp, ds:[di] ;设置显存起始地址
mov si, 0 ;设置句子起始地址
s1: mov al, ds:[si] ;设置字型
mov ah, ds:[bx] ;设置颜色
mov es:[bp], ax ;写入显存
add bp, 2 ;移动
inc si
loop s1
pop cx ;取回外部 cx
add bx, 1 ;移到下一个颜色
add di, 2 ;移到显存下一个起始地址
loop s0
mov ax, 4c00H
int 21H
code ends
end start
运行结果:

实验任务 2
编写子程序 printStr,实现以指定颜色在屏幕上输出字符串、调用它完成字符串输出。
task2.asm
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
运行结果:

把 line3 改为:
str db 'another try', 0
把 line12 改为:
mov al, 4
运行结果:

基于运行结果,理解源代码,以及,组合使用转移指令 call 和 ret 实现子程序的原理和方法。具体的,在 line18-40 中:
- line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?
在本程序中,存在子程序的调用,在子程序调用前,需要把子程序中使用到的各寄存器的值放入栈内存储,防止被覆盖。在返回父程序后,再将站内的值取出返回各寄存器,即可继续父程序的运行 - line30 的功能是什么
ds:[si]内的值为字符,将其放入 cl,ch 值设为 0,此时若 cx 寄存器内的值为 0,说明已经完成了字符串的输出,即可终止当前子程序,进入 over。
实验任务 3
task3.asm
子任务 1:
对 task3.asm 进行汇编、链接,得到可执行程序后,在 debug 中使用 u 命令反汇编,使用 g 命令执行到 line 15(程序退出之前),使用 d 命令查看数据段内容,观察是否把转换后的字符串 ‘1984’ 存放到在数据段中 str 标号后面的单元。

成功
子任务 2:
对 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
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
运行结果:

把 task3.asm,line3 中整数换成0~2559之中任意数值,运行测试,观察结果:


颜色与背景色与 al 相关,ax = x
实验任务 4
task4.asm
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
运行结果:

-
line12-19 实现的功能:
读入字符直到 # 为止 -
line21-27 实现的功能:
输出先前输入的字符串
实验任务 5
在 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);
}
在 line7 和 line13 分别设置断点,在调试模式下,查看反汇编代码:

在函数调用处,将[b],[a]对应的值移给 eax 与 ecx 寄存器,然后将两个寄存器中的值存入栈内,参数入栈约定为自右向左,然后通过 call 跳转到对应的 sum 函数处。
sum 函数完成后,将 eax 寄存器内的值传给 [c],函数完成。

sum 函数中,通过 [x] 直接获取值并将其移入 eax,将 [y] 对应的值加给 eax,通过 eax 实现返回值,完成加法运算。一系列操作后 ret,回到主程序。
实验结论
分享:C语言函数调用反汇编内容详细可见:https://blog.csdn.net/songjinshi/article/details/8450419

浙公网安备 33010602011771号