汇编语言笔记课程设计一

汇编语言笔记课程设计一

0x00 任务一

QQ截图20200603090404

QQ截图20200603090433

QQ截图20200603091128

​ 需求分析:这个课设,主要是 1字符串显示,但是提示也说了 显示的数字大于65536 16位,所以在除10时应该用 32位除16位 而且结果商也要为32位才行 余数16位 2除法不溢出 也就是32位商的实现 昨天的实验10任务二写过

​ 所以 上代码

assume cs:code,ds:data,ss:stack
data segment
		db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
		db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
		db '1993','1994','1995'
		dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,1975114
		dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
		dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
		dw 11542,14430,15257,17800
data ends
data1 segment
		db 16 dup (0)
data1 ends
stack segment
		db 64 dup (0)
stack ends
code segment
start: 	mov ax,data
		mov es,ax
		mov ax,data1
		mov ds,ax
		mov ax,stack
		mov ss,ax
		mov sp,40h
		
		mov ah,0
		mov al,0
		mov si,0
		mov bx,0
		mov cx,21
s0:		mov dh,ah
		mov dl,al
		call print_str
		
		
		push si
		push ax
		
		mov si,0
		mov ax,21
		sub ax,cx
		mov ah,4
		mul ah
		mov di,ax
		mov ax,es:[84+di]
		mov dx,es:[86+di]
		call dtoc
		
		pop ax
		
		mov dh,ah
		mov dl,al
		add dl,10
		mov si,0
		call show_str1
		
		pop si
		
		inc ah
		loop s0
		mov ax,4c00h
		int 21h
show_str1:
		push cx
		push ax; dh 行 dl列  dssi初始地址
		push bx
		push es
		mov ax,0b800h
		mov es,ax
		mov al,160
		mul dh
		mov bx,ax
		add dl,dl
		mov dh,0
		add bx,dx
sq:		mov cl,ds:[si]
		mov ch,0
		jcxz fin1
		mov es:[bx],cl
        mov byte ptr es:[bx+1],2
        add bx,2
        inc si
        jmp short sq
fin1:    pop es
        pop bx
        pop ax
        pop cx
        ret
print_str:push ax;行dh 列dl 字符串首位 es:[si] 长度默认4
		push cx
		push ds
		push di
		mov al,160
		mul dh
		add dl,dl
		mov dh,0
		add ax,dx
		mov di,ax
		mov ax,0b800h
		mov ds,ax
		mov cx,4
s1:		mov al,es:[si]
		mov ds:[di],al
		mov byte ptr ds:[di+1],2
		add di,2
		inc si
		loop s1
		pop di
		pop ds
		pop cx
		pop ax
		ret
		
dtoc:	push cx;参数 ax要转换的数低16位 dx 高16位 ds:[si]首地址
		push bx
		mov bx,0
s1s:	mov cx,10
		call divdw
		push cx
		inc bx
		push ax
		add ax,dx;必须ax dx 也就是商的高16位和低16位都为0才行,所以加起来判断
		mov cx,ax
		pop ax
		jcxz s2
		jmp short s1s
s2:		mov cx,bx
s3:		pop dx
		add dl,30h
		mov ds:[si],dl
		inc si
		loop s3
		mov byte ptr ds:[si],0
		inc si
		pop bx
		pop cx
		ret

divdw:	push bx;参数 ax存放低位 dx存放高位 cx存放除数
		push bp;结果 ax存放商低位 dx存放高位 cx存放 余数
		mov bp,sp
		sub sp,12
		mov [bp-2],ax;保存传入参数ax
		mov [bp-4],dx;保存传入参数dx
		mov [bp-6],cx;保存传入参数cx
		mov ax,dx
		mov dx,0
		div cx
		mov [bp-8],ax;
		mov ax,[bp-2]
		div cx;(rem(H/N)*65536+L)/N
		mov [bp-10],ax;
		mov [bp-12],dx;-12
		
		mov dx,word ptr [bp-8]
		mov ax,word ptr [bp-10]
		mov cx,word ptr [bp-12]
		add sp,12
		pop bp 
		pop bx
		ret
code ends
end start

​ 代码没有实现所有细节,但是主体共能全部实现了,这是一份非常复杂,非常需要细心的代码,发现了昨天写的实验10中的函数的很多问题,已经改正了。上述代码运行结果如下:

QQ截图20200603113637

//2020-6-3下午修改:

​ 好吧我是个实事求是的人,没完成就是没完成,我把代码补充完整了,下面是完成效果和完整代码:

QQ截图20200603170339

assume cs:code,ds:data,ss:stack
data segment
		db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
		db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
		db '1993','1994','1995'
		dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,1975114
		dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
		dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
		dw 11542,14430,15257,17800
data ends
data1 segment
		db 16 dup (0)
data1 ends
stack segment
		db 64 dup (0)
stack ends
code segment
start: 		mov ax,data
		mov es,ax
		mov ax,data1
		mov ds,ax
		mov ax,stack
		mov ss,ax
		mov sp,40h
		mov cx,21

s0:		call p_o_l
		inc dh
		loop s0
		mov ax,4c00h
		int 21h
		

p_o_l:		push si
		push di
		push bx
		push ax
		push cx
		mov dl,1
		mov ax,21

		sub ax,cx
		mov bx,ax
		mov dh,al
		add ax,ax
		add ax,ax
		mov si,ax
		call print_str
		
		mov si,0
		mov ax,bx
		add ax,ax
		add ax,ax
		mov di,ax
		mov ax,es:[84+di]
		mov dx,es:[86+di]
		call dtoc
		
		mov dh,bl
		mov dl,10
		mov si,0
		call print_str0
		
		mov si,0
		mov ax,bx
		add ax,ax
		mov di,ax
		mov ax,es:[168+di]
		mov dx,0
		call dtoc
		
		mov dh,bl
		mov dl,20
		mov si,0
		call print_str0
		
		mov ax,bx
		add ax,ax
		mov si,ax
		add ax,ax
		mov di,ax
		mov ax,es:[84+di]
		mov dx,es:[86+di]
		mov cx,es:[168+si]
		call divdw
		mov si,0
		call dtoc
		
		mov dh,bl
		mov dl,30
		mov si,0
		call print_str0

		pop cx
		pop ax
		pop bx
		pop di
		pop si
		ret
		
print_str0:		push cx
		push ax; dh 行 dl列  dssi初始地址
		push bx
		push es
		mov ax,0b800h
		mov es,ax
		mov al,160
		mul dh
		mov bx,ax
		add dl,dl
		mov dh,0
		add bx,dx
sq:		mov cl,ds:[si]
		mov ch,0
		jcxz fin1
		mov es:[bx],cl
        		mov byte ptr es:[bx+1],2
        		add bx,2
        		inc si
        		jmp short sq
fin1:    		pop es
        		pop bx
        		pop ax
        		pop cx
        		ret

print_str:		push ax;行dh 列dl 字符串首位 es:[si] 长度默认4
		push cx
		push ds
		push di
		mov al,160
		mul dh
		add dl,dl
		mov dh,0
		add ax,dx
		mov di,ax
		mov ax,0b800h
		mov ds,ax
		mov cx,4
s1:		mov al,es:[si]
		mov ds:[di],al
		mov byte ptr ds:[di+1],2
		add di,2
		inc si
		loop s1
		pop di
		pop ds
		pop cx
		pop ax
		ret
		
dtoc:		push cx;参数 ax要转换的数低16位 dx 高16位 ds:[si]首地址
		push bx
		mov bx,0
s1s:		mov cx,10
		call divdw
		push cx
		inc bx
		push ax
		add ax,dx;必须ax dx 也就是商的高16位和低16位都为0才行,所以加起来判断
		mov cx,ax
		pop ax
		jcxz s2
		jmp short s1s
s2:		mov cx,bx
s3:		pop dx
		add dl,30h
		mov ds:[si],dl
		inc si
		loop s3
		mov byte ptr ds:[si],0
		inc si
		pop bx
		pop cx
		ret

divdw:		push bx;参数 ax存放低位 dx存放高位 cx存放除数
		push bp;结果 ax存放商低位 dx存放高位 cx存放 余数
		mov bp,sp
		sub sp,12
		mov [bp-2],ax;保存传入参数ax
		mov [bp-4],dx;保存传入参数dx
		mov [bp-6],cx;保存传入参数cx
		mov ax,dx
		mov dx,0
		div cx
		mov [bp-8],ax;
		mov ax,[bp-2]
		div cx;(rem(H/N)*65536+L)/N
		mov [bp-10],ax;
		mov [bp-12],dx;-12
		
		mov dx,word ptr [bp-8]
		mov ax,word ptr [bp-10]
		mov cx,word ptr [bp-12]
		add sp,12
		pop bp 
		pop bx
		ret
code ends
end start

0x01 课设总结

1.写汇编真的是一件很辛苦的事情,因为没有很多语法糖,需要注意很多细节,一不小心就错了

2.除了必要操作(div mul loop jcxz)等非要使用寄存器不可得操作,尽量不用寄存器保存中间值,因为寄存器就那么几个,用来用去难逃一bug,使用局部变量(创建局部变量用栈,改sp 用mov 读写 然后又改回sp 详情见《实验10》里)

3.如果实在要使用寄存器,那么如果要修改,在函数开头一定要push 入栈保存 结尾恢复