[Assembly Language] 实验4 汇编应用编程和c语言程序反汇编分析
Task1 在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcome to masm!'
编写程序如下:
1 assume cs:codesg, ds:datasg 2 3 datasg segment 4 db 'welcome to masm!'; 5 db 02H,24H,71H; 6 datasg ends 7 8 codesg segment 9 start: 10 mov ax, datasg 11 mov ds, ax 12 mov ax, 0b800h 13 mov es, ax 14 mov di, 1984;初始偏移位置,第一行位置 15 16 mov cx, 4;三行循环三次 17 mov bx, 0;从datasg的第一个位置开始 18 s1: push cx;保存外层循环 19 mov cx,16;16个字符,循环16次 20 mov si,0;字符数据的偏移地址 21 s2: mov al,ds:[si];字符样式 22 mov ah,ds:[bx+16];颜色样式 23 mov es:[di],ax;输出到指定地址 24 inc si;下一个字符指针 25 add di,2;下一个输出位置指针 26 loop s2 27 pop cx; 28 inc bx;切换下一个颜色 29 add di, 128;到下一行的起始位置 30 loop s1; 31 32 mov ah,4ch; 33 int 21h 34 35 codesg ends 36 end start
效果如下:

实现原理已注释在代码中。
Task2 编写子程序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 str12 mov al, 213 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 ret41 42 code ends 43 end start
运行结果如下:

将第三行改成 str db 'another try', 0 ,第12行改成 mov al, 4,结果如下:

line19-22, line36-39,这组对称使用的push、pop,这样用的目的是为了将工作状态保存在栈中,当函数结束后,再从栈中恢复工作状态。这样可以确保调用函数前后对无关寄存器不产生副作用。(原理与C语言函数开栈类似)
line30的功能参考task1,即将cx中带颜色样式的字符保存到显示器对应地址,相当于输出到显示器中。
Task3 使用任意文本编辑器,录入汇编源程序task3.asm
代码如下:
1 assume cs:code, ds:data 2 3 data segment 4 str db 'another try', 0 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov si, offset str 12 mov al, 4 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 s: mov cl, [si] 27 mov ch, 0 28 jcxz over 29 mov ch, al 30 mov es:[di], cx 31 inc si 32 add di, 2 33 jmp s 34 35 over: 36 pop di 37 pop si 38 pop cx 39 pop bx 40 ret 41 42 code ends 43 end start
子任务1,运行到程序结束前,查看ds里的数据:

子任务2,加入输出到屏幕的子函数,代码如下:
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 mov si, offset str 15 mov al, 2 16 mov di, 0 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 52 printStr: 53 push bx 54 push cx 55 push si 56 push di 57 58 mov bx, 0b800H 59 mov es, bx 60 s: mov cl, [si] 61 mov ch, 0 62 jcxz over 63 mov ch, al 64 mov es:[di], cx 65 inc si 66 add di, 2 67 jmp s 68 69 over: 70 pop di 71 pop si 72 pop cx 73 pop bx 74 ret 75 76 code ends 77 end start
运行结果如下:

Task4 使用任意文本编辑器,录入汇编源程序task4.asm
代码如下:
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-line19 将输入的字符利用si作为指针保存到ds中,并判断是否为#,如果是#则结束输入,否则继续读入新的字符。
line21-line27 将保存在ds中的字符逐个输出到#后面。
Task5 在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 }
在line7、line13插入断点,查看汇编:


高级语言调用函数主要使用call指令,寄存器eax,ecx等,以及一个工作栈完成。
函数传参的原理,即先保存各种寄存器的工作状态,再将参数压入到栈中,待跳转到函数所在地址开始执行时,先取出栈中的参数,再执行。
函数返回后,各个寄存器的状态从栈中恢复。

浙公网安备 33010602011771号