实验4 汇编应用编程和c语言程序反汇编分析
1. 实验任务1
教材「实验9 根据材料编程」(P187-189)
编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcome to masm!'。
1 assume cs:code, ds:data 2 data segment 3 db 'welcome to masm!' 4 db 00000010B,00100100B,01110001B 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 12 mov ax, 0b800H 13 mov es, ax 14 15 mov cx,3 16 mov bx,0 17 mov di, 1760+64 18 19 s0: push cx 20 mov cx, 16 21 mov si, 0 22 23 s1: mov al, [si] 24 mov es:[di], al 25 mov al, [16+bx] 26 mov es:[di+1], al 27 inc si 28 add di, 2 29 loop s1 30 31 pop cx 32 inc bx 33 add di,128 34 loop s0 35 36 mov ah, 4ch 37 int 21h 38 code ends 39 end start
- 屏幕中间对应的显存位置的计算:在80*25彩色字符模式下,显示器可以显示25行,每行80个字符,即160个字节
所以中间行是11~13行;中间列是64~95
- data的前16个字节存放字符信息,后面三个是颜色信息
00000010B, 绿色
00100100B, 绿底红色
01110001B, 白底蓝色
- 主要是两个循环,内循环每次输入16个字符,外循环则控制3次字符串的输出,在外循环选择颜色信息
2. 实验任务2
编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。
1 assume cs:code, ds:data 2 data segment 3 str db 'try', 0 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 11 mov si, offset str 12 mov al, 2 13 call printStr 14 15 mov ah, 4ch 16 int 21h 17 18 printStr: 19 push bx 20 push cx 21 push si 22 push di 23 24 mov bx, 0b800H 25 mov es, bx 26 mov di, 0 27 s: mov cl, [si] 28 mov ch, 0 29 jcxz over 30 mov ch, al 31 mov es:[di], cx 32 inc si 33 add di, 2 34 jmp s 35 36 over: pop di 37 pop si 38 pop cx 39 pop bx 40 ret 41 42 code ends 43 end start
把line3改为:
str db 'another try', 0
把line12改为:
mov al, 4
- line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?
将寄存器的值存入栈中,可暂时释放寄存器,用于其他数据存储,再依次出栈,防止数据错乱
- line30的功能是什么?
把数据放入显示缓冲区,低字节是字符信息,高字节是颜色信息
3. 实验任务3
使用任意文本编辑器,录入汇编源程序task3.asm。
1 assume cs:code, ds:data 2 data segment 3 x dw 1984 4 str db 16 dup(0) 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov ax, x 12 mov di, offset str 13 call num2str 14 15 mov ah, 4ch 16 int 21h 17 18 num2str: 19 push ax 20 push bx 21 push cx 22 push dx 23 24 mov cx, 0 25 mov bl, 10 26 s1: 27 div bl 28 inc cx 29 mov dl, ah 30 push dx 31 mov ah, 0 32 cmp al, 0 33 jne s1 34 s2: 35 pop dx 36 or dl, 30h 37 mov [di], dl 38 inc di 39 loop s2 40 41 pop dx 42 pop cx 43 pop bx 44 pop ax 45 46 ret 47 code ends 48 end start
子任务1
对task3.asm进行汇编、链接,得到可执行程序后,在debug中使用u命令反汇编,使用g命令执行 到line15(程序退出之前),使用d命令查看数据段内容,观察是否把转换后的数字字符串'1984'存放 在数据段中str标号后面的单元。
子任务2
对task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来, 实现对转换后的字符串进行输出。
1 assume cs:code, ds:data 2 data segment 3 x dw 1999 4 str db 16 dup(0) 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov ax, x 12 mov di, offset str 13 call num2str 14 15 mov si,offset str 16 mov al,2 17 call printStr 18 19 mov ah, 4ch 20 int 21h 21 22 num2str: 23 push ax 24 push bx 25 push cx 26 push dx 27 28 mov cx, 0 29 mov bl, 10 30 s1: 31 div bl 32 inc cx 33 mov dl, ah 34 push dx 35 mov ah, 0 36 cmp al, 0 37 jne s1 38 s2: 39 pop dx 40 or dl, 30h 41 mov [di], dl 42 inc di 43 loop s2 44 45 pop dx 46 pop cx 47 pop bx 48 pop ax 49 50 ret 51 printStr: 52 push bx 53 push cx 54 push si 55 push di 56 57 58 mov bx, 0b800H 59 mov es, bx 60 mov di, 0 61 s: mov cl, [si] 62 mov ch, 0 63 jcxz over 64 mov ch, al 65 mov es:[di], cx 66 inc si 67 add di, 2 68 jmp s 69 70 over: pop di 71 pop si 72 pop cx 73 pop bx 74 ret 75 code ends 76 end start
4. 实验任务4
1 assume cs:code, ds:data 2 data segment 3 str db 80 dup(?) 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 mov si, 0 11 12 s1: 13 mov ah, 1 14 int 21h 15 mov [si], al 16 cmp al, '#' 17 je next 18 inc si 19 jmp s1 20 next: 21 mov cx, si 22 mov si, 0 23 s2: mov ah, 2 24 mov dl, [si] 25 int 21h 26 inc si 27 loop s2 28 29 mov ah, 4ch 30 int 21h 31 code ends 32 end start
- line12-19实现的功能是?
从键盘输入字符,直到遇到‘#’则跳到next段执行,否则一直循环
cmp是比较指令,执行后对标志寄存器产生影响
je跳转函数,比较后相等则跳转
- line21-27实现的功能是?
使用int 21h的2号子功能,在屏幕输出单个字符
mov cx, si ;字符串长度即为要循环的次数
5. 实验任务5
在visual studio集成环境中,编写一个简单的包含有函数调用的c程序。代码如下:
1 #include <stdio.h> 2 int sum(int, int); 3 4 int main() { 5 int a = 2, b = 7, c; 6 7 c = sum(a, b); 8 9 return 0; 10 } 11 12 int sum(int x, int y) { 13 return (x + y); 14 }
高级语言中参数传递,从汇编的角度是如何传递的,返回值是如何返回的;多个参数的入栈顺序 是什么样的;函数调用栈,等
调用函数时,先把参数压入栈,然后利用call指令将函数返回地址入栈。且如上图所示,b先入栈,a再入栈。
call指令执行时自动将函数返回地址入栈,之后转到sum函数开始执行此函数。最后把返回值赋给c
在函数体内,进行各寄存器初始化,将oxcccH存入ax寄存器。然后把x的值移入ax寄存器,再与bx相加。也就解释了主函数部分把ax寄存器的值送给c