实验4 汇编应用编程和c语言程序反汇编分析

2021-03-11 06:32

阅读:316

标签:格式   指示   开始   jmp   执行   包含   中间   一个   调用函数   

实验四


实验任务1

任务内容:

教材「实验9 根据材料编程」(P187-189)

编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串‘welcome to masm!‘。
程序正确编写后,预期输出结果如下:

实验结果

assume cs:code
data segment
  db ‘welcome to masm!‘
  db 2,36,113
data ends
code segment
start:
		mov ax,data
		mov ds,ax

		mov ax,0b86eH
		mov es,ax
		mov bx,0
		mov cx,3
	
s1:		push cx
	
		mov cx,16
		mov si,0
		mov di,64
s:		mov al,[si]
		mov es:[di],al
		mov al,[16+bx]
		mov es:[di+1],al
		inc si
		add di,2
		loop s
	
		inc bx
		mov ax,es
		add ax,0ah
		mov es,ax
	
		pop cx
		loop s1
	
		mov ax,4c00h
        int 21h
code ends
end start



技术图片

代码分析

  1. data段:
    1. 首先将字符串‘welcome to masm!‘存入内存
    2. 再计算出要求的颜色(绿色、绿底红色、白底蓝色)对应的颜色属性为2,36,113(10进制)
  2. code段:
    1. 将data地址赋值给ds,用于将数据段数据存入指定内存地址
    2. 计算屏幕中间上一排对应的段地址为0b86eh,并将其赋值给额外数据段es
    3. mov bx,0 用bx标记当前输出行数
    4. mov cx,0需要输出三行,因此外层循环为3次
    5. 需要嵌套使用loop指令因此将当前cx压入栈,并标记为s1
    6. 内存循环:共16个字符,因此循环16次
    7. 计算输出到中间列的起始列偏移量为64,因此mov di,64,并将字符赋值到es:[di]
    8. 对应的颜色属性为[16+bx],将其赋值到es:[di+1]
    9. 一行输出结束,进入下一行,将es+0ah
    10. pop cx进入下一循环

实验任务2

任务内容

编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。子程序printSar

功能:以指定颜色在屏幕上(从屏幕左上角开始)输出字符串
要求:字符串以0结尾
入口参数
字符串的起始地址—> ds: si (其中,字符串所在段的段地址—> ds, 字符串起始地址
的偏移地址—> si
字符串颜色—> al
出口参数:无

代码

assume cs:code, ds:data
data segment
    str db ‘another try‘, 0
data ends

code segment
start:  
	mov ax, data
	mov ds, ax

	mov si, offset str
	mov al, 4
	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

输出结果

技术图片
技术图片

代码分析

  1. 11行:mov si,offset str 使用offset 指令,计算字符串的偏移量
  2. 12行:mov al,2 mov al,4 2、4分别为绿字和红字的颜色属性
  3. 13行:call printStr 即跳转至printStr
  4. 19-22行:将参数存储,便于再次调用函数
  5. 26-29行:将字符串存入cl,ch置0
    1. 若字符为0,即字符串结束,则cx为0,则29行执行跳转操作,跳转至over处,恢复参数并返回
    2. 若字符不为0,则继续执行下一语句
  6. 30行:将字符的颜色属性存到内存单元的高地址
  7. 30-33行:输出字符

实验任务3

子任务1

任务内容

使用任意文本编辑器,录入汇编源程序task3.asm。

子程序num2str:
功能:把0~2559之间的任意整数转换成数字字符串,例如,把1984转换成‘1984‘
入口参数
要转换的整数 —> ax
数字字符串的起始地址 —> ds:di (其中:数字字符串所在段的段地址—> ds,字符串
起始地址的偏移地址—>di)
出口参数:无

代码

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

输出结果

  • 执行前:
  • 技术图片
  • 执行后:
  • 技术图片

代码分析

  1. 9-12行:data段地址赋值到ds,1984(07c0h)赋值给x,str的偏移量赋值给di
  2. 18-46行:num2str函数
    1. 19-22行、41-44行,将参数存储起来,便于二次调用函数
    2. cx指示位数,每除一次就+1,便于之后出栈存储标明循环次数
    3. s1循环:
      1. div bl div指令将除数存储在bl中,被除数在ax中(11行赋值),结果商在al中,余数在ah
      2. push dx将余数压入栈
      3. cmp al,0,若al==0,的zf=1
      4. jne s1 zf!=0,则跳转到s1,以此实现循环除10,直到商为0,余数入栈
    4. s2循环:or dl 30h 将数字转换为字符

子任务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	
		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 ax
		push bx
		push cx
		push dx

		mov bx, 0b800H
		mov es, bx
		mov di, 0
		mov al,2
		mov si,offset str
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 dx
        pop cx
        pop bx
        pop ax
		ret
code ends
end start

输出结果

技术图片

实验任务4

任务内容

汇编、链接、运行程序,输入一个字符串并以#结束(比如,2020, bye#)观察运行结果。结合运行结
果,理解程序功能,了解软中断指令。

代码

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

输出结果

技术图片

代码分析

  1. 12-19行:
    1. mov ah,1; int 21h;从键盘输入,输入结果存入al中
    2. cmp al,‘#‘ 当al==‘#‘时,zf=1
    3. je next当zf=1时,跳转到next,即输入结束,反正进入下一语句,继续输入
  2. 21-27行:
    1. mov ah,2; mov dl,[si]; int 21h;将[si]输出到屏幕
  3. 即代码实现将键盘输入的内容输出

实验任务5

任务内容

在visual studio集成环境中,编写一个简单的包含有函数调用的c程序。代码如下:

#include
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);

}

反汇编结果

技术图片
技术图片

反汇编分析

  1. 函数(包括main函数)在执行刚开始都有一段入栈操作,而在结束前又都有一段相对应的出栈操作,这应该是对函数调用栈的相关操作,用于结束函数时恢复现场
  2. 调用函数时,会先将参数从右往左压入栈,以保存参数
  3. 函数结果通过eax返回,main函数中,mov dword ptr [c],eax即说明这一点

总结

  1. 80×25彩色字符模式显示缓冲区结构,通过这一结构,可以进行计算想要显示在屏幕的位置对应的内存地址
  2. 将数据存储到显存对于地址的格式,低地址al存放字符,高地址ah存放颜色属性
  3. callret的结合使用,使用时在函数开始和结尾应当对寄存器数据进行入栈出栈操作,以避免对函数结束后造成影响
  4. 数字的显示方法,即实验3已经对两位数进行了讨论,本实验进一步通过cmpjne指令的结合使用实现了表示范围内任意数字的输出
  5. 通过对cpp程序的反汇编,更直接的认识了高级语言中程序的底层实现方式

实验4 汇编应用编程和c语言程序反汇编分析

标签:格式   指示   开始   jmp   执行   包含   中间   一个   调用函数   

原文地址:https://www.cnblogs.com/PestLa/p/14130640.html


评论


亲,登录后才可以留言!