汇编笔记

DOS环境下Debug的使用

<code class="python">-a 进入指令编辑模式,在该模式下默认为16进制,不用加h,后接数字可以修改指定行,如 -a 104
-u 查看源程序
-e 修改内存,例如e ds:200h 修改200h下内存,按空格修改下一个
-r 查看寄存器状态,该指令也可以用于修改寄存器值,例如-r ip,可以修改ip值
-d 查看内存状态,例如 d ds:200h
-g 执行指令,-g [程序地址] 可以执行到制定地址处

常用中断

<code class="txt">int 01h ;1号中断,从标准输入设备输入一个字符,ascii码输入到AL内
int 02h ;2号中断,向标准输出设备输出一个字符,字符ascii存于DL内
int 09h ;9号中断,输出一个字符串,字符串开始地址是ds:dx,故需要offset或者lea给dx赋值。
int 0Ah ;10号中断,输入一个字符串。同样存于ds:dx内

Program1

使用地址表实现如下功能:根据输入的数字1-7,分别显示相应的英文星期名,如果输入其他字符,则重新输入。
这个程序使用了简化的地址表,直接把day1,day2的地址给table。
另外,需要注意的是,table由于是dw,寻址方式为双字节。例如dw[2]指向day2的地址。

<code class="asm">assume cs:code,ds:data
data segment
msg db 'Input number(1~7)',0dh,0ah,'$'
errormsg db 'Wrong input, Please input again',0dh,0ah,'$'
day1 db 'Monday',0dh,0ah,'$'
day2 db 'Tuesday',0dh,0ah,'$'
day3 db 'Wednesday',0dh,0ah,'$'
day4 db 'Thurdasy',0dh,0ah,'$'
day5 db 'Friday',0dh,0ah,'$'
day6 db 'Saturday',0dh,0ah,'$'
day7 db 'Sunday',0dh,0ah,'$'
table dw day1,day2,day3,day4,day5,day6,day7
data ends
code segment
error:  mov dx,offset errormsg
        mov ah,9
        int 21h
start:  mov ax,data
        mov ds,ax
        mov dx,offset msg
        mov ah,9
        int 21h
        mov ah,1
        int 21h
        cmp al,'1'
        jb error
        cmp al,'7'
        ja error
        and ax,000fh
        dec ax
        shl ax,1
        mov bx,ax
        mov dx,table[bx]
        mov ah,9
        int 21h
        mov ax,4c00h
        int 21h
code ends
end start

Program2

求一个班50名学生成绩的平均值、最大值和最小值,并将结果显示出来。
这个程序主要难点在于dec2asc这个子程序,用于解决将十进制数转换为ascii码。

因为9号中断只能显示ds:dx内的ascii码内容,所以在显示结果是,要将十进制数转换为ascii码。这个子程序使用mod10来取出原十进制数的每一位,add ‘0’转换为ascii码,并且用栈来逆序。

例如321d,三次mod10后,加上’0′,栈内容为,’1′,’2′,’3’;pop出栈后为’3′,’2′,’1’;即可正常显示。

<code class="asm">assume ds:data,cs:code
data segment 
min dw ?
max dw ?
avg dw ?
score dw 49, 57, 73, 49, 41, 71, 72, 92, 94, 30, 86, 72, 32, 68, 45, 40, 52, 88, 63, 86, 36, 96, 47, 64, 63, 36, 58, 35, 47, 67, 49, 72, 92, 77, 58, 52, 61, 56, 59, 50, 48, 41, 53, 79, 44, 73, 55, 40, 47, 71
data ends
code segment
start: mov ax,data
       mov ds,ax
       mov cx,50d
       xor bx,bx
       xor ax,ax
       xor dl,dl
       xor dh,dh
bianli:   add ax,score[bx]
          cmp dl,byte ptr score[bx]
          jnl buhuan
          mov dl,byte ptr score[bx]
buhuan:   add bx,2
          loop bianli
          mov dh,32h
          div dh
          mov avg[0],ax
          xor dh,dh
          mov max[0],dx
          xor ax,ax
          mov cx,50d
          xor bx,bx
          mov ax,score[0]
newbi:    cmp ax,score[bx]
          jb buhuan2
          mov ax,score[bx]
buhuan2:  add bx,2
          loop newbi
          mov min[0],ax
          call dec2asc
          mov ax,max[0]
          call dec2asc
          mov ax,avg[0]
          xor ah,ah
          call dec2asc
          mov ax,4c00h
          int 21h
dec2asc     proc
        push    ax
        push    dx
        push    cx
        mov    dx, -1    
        push    dx   
        mov    cx, 10
l_div10:
        xor    dx, dx
        div    cx   
        push    dx
        test    ax, ax
        jne    l_div10
        mov    cx, -1
        mov    ah, 2    
l_disp:
        pop    dx
        cmp    dx, cx
        je    l_ret
        add    dl, '0'  
        int    21h   
        jmp    l_disp
l_ret:
        pop    cx
        pop    dx
        pop    ax
        ret
dec2asc        endp
code ends
end start

Program3

从键盘读入一个字符串,以Enter结束,字符串不超过50个字符,并打印该字符串(附加题:查找中间是否有‘asm’子串。如果有,输出‘Yes’;否则,输出‘No’)。

这一题难点在于字符串的查找。使用状态机处理。过程如下图:

<code class="asm">assume ds:data,cs:code
data segment
input db 50,0,50 dup(0)
msg db 'Please input a string:',0dh,0ah,'$'
enter db 0dh,0ah,'echo:',0dh,0ah,'$'
findstring db 0dh,0ah,'Yes',0dh,0ah,'$'
notfindstring db 0dh,0ah,'No',0dh,0ah,'$'
data ends
code segment
start:mov ax,data
mov ds,ax
mov dx,offset msg
mov ah,9
int 21h
lea dx,input
mov ah,0ah
int 21h
mov cx,50
mov bx,0
compare:mov al,input[bx]
cmp al,0h
je final
inc bx
loop compare
final:mov input[bx],'$'
mov dx,offset enter
mov ah,9
int 21h
mov dx,offset input[2]
int 21h
mov bx,1
mov cx,50
find1:inc bx
cmp input[bx],'a'
je find2
cmp input[bx],'$'
je notfind
loop find1
find2:inc bx
cmp input[bx],'s'
je find3
cmp input[bx],'$'
je notfind
loop find1
find3:inc bx
cmp input[bx],'m'
je find4
cmp input[bx],'$'
je notfind
loop find1
find4:mov dx,offset findstring
mov ah,9
int 21h
jmp done
notfind:mov dx,offset notfindstring
mov ah,9
int 21h
done:mov ah,04ch
int 21h
code ends
end start