汇编语言笔记课程设计一
汇编语言笔记课程设计一
0x00 任务一
需求分析:这个课设,主要是 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中的函数的很多问题,已经改正了。上述代码运行结果如下:
//2020-6-3下午修改:
好吧我是个实事求是的人,没完成就是没完成,我把代码补充完整了,下面是完成效果和完整代码:
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 入栈保存 结尾恢复