yundi 发表于 2016-1-7 22:58:47

第十章检测实验及笔记

本帖最后由 yundi 于 2016-1-8 14:49 编辑

先来个实验10的第2题,解决除法溢出问题。

一张图理顺寄存器变化


;不溢出的除法子程序
;自己发明的表示法:(dx)(ax)/(cx)=(dx)(ax)...(cx)
assume cs:code
code segment
start:        mov dx,000fh
                mov ax,4240h
                mov cx,0ah
                call divdw

                mov ax,4c00h
                int 21h

divdw:
                ;1.先处理被除数高16位(dx)的除法               
                push bx;子程序用到的寄存器,先入栈保存
                push ax;被除数低16位(ax)后面要用,也保存到栈中
                mov ax,dx;因为除数(cx)16位,所以把高16位放到(ax)
                xor dx,dx;同时让(dx)为0
                div cx;然后相除(dx)(ax)/(cx)=(ax)...(dx)
                ;2.再处理被除数低16位(ax)的除法
                pop bx;被除数低16位出栈
                push ax;栈保存高16位除后的商
                ;现在的(dx)保存高16位除后的余数,正好下步可用
                ;公式中余数*65536,为何此处(dx)不乘?
                mov ax,bx
                div cx;(dx)(ax)/(cx)=(ax)...(dx),(ax)正好是结果的低16位
                mov cx,dx;结果的余数放入cx
                pop dx;取出高16位除后的商(dx),正好是结果的高16位
                ;公式中需要*65536,为何此处(dx)直接是结果?
                pop bx;取出bx原始值
                ret
code ends
end start

yundi 发表于 2016-1-8 09:08:30

接着是实验10第1题
;子程序练习
;名称:show_str
;功能:按给定参数输出0结尾的字符串
assume cs:code
data segment
        db 'Welcome to masm!',0
data ends

code segment
start:        mov dh,8        ;行号
                        mov dl,3        ;列号
                        mov cl,2        ;颜色属性
               
                        mov ax,data
                        mov ds,ax
                        mov si,0        ;串首
                        call show_str;子程序
                       
                        mov ax,4c00h
                        int 21h
                       
show_str:
                        push ax
                        push es
                       
                        ;找偏移 (es):(dh)*160+(dl)*2
                        mov ax,0b800h
                        mov es,ax
                        mov al,160
                        mul dh        ;结果在(ax)
                        mov bx,ax
                        mov al,2
                        mul dl
                        add bx,ax        ;偏移(bx)
                       
                        ;循环读字符并写入
                        mov ah,cl;先保存颜色属性
                        xor cx,cx;清空cx               
        s0:        mov cl,ds:;取出data中第si个字符
                        jcxz ok;(cx)=0如果字符为0跳到ok
                        mov al,cl;暂存字符
                        mov es:,ax;此时 (ah)=颜色属性,(al)=字符,将其保存到b800:偏移 中
                        inc si;下个字符
                        add bx,2;下个显存位置
                        jmp short s0
                       
        ok:        pop es
                        pop ax
                        ret
code ends
end start

yundi 发表于 2016-1-9 14:45:05

实验10的第3题,代码越来越长。不知到win32汇编是啥状况。

;名称:dtoc
;功能:将word型数据变为十进制字符串,0结尾
;参数:(ax) = word型数据
;                ds:si 串首

assume cs:code

data segment
        db 10 dup (0)
data ends

code segment
start:        mov ax,12666
                mov bx,data
                mov ds,bx
                mov si,0
                call dtoc;调用子程序,将数据变为字符串并保存到指定位置
               
                mov dh,8
                mov dl,3
                mov cl,2
                mov si,0
                call show_str;调用输出子程序
               
                mov ax,4c00h
                int 21h
               
dtoc:       
                push cx
s0:                mov cx,ax
                jcxz ok1;被除数为0表示循环结束,跳出
                mov bx,10;12666/10=1266>256,商要用(ax)保存,所以除数要16位(bx),不能(bl)
                xor dx,dx;12666<65536,除数16位,则被除数必须用到(dx),12666<65536,(dx)置0即可
                div bx;除后的结果 (ax)...(dx)
                push dx;保存余数,并将(ax)作为下次循环的被除数
                inc si;记录循环次数,求得字符串长度
                jmp short s0               
ok1:        mov cx,si
                xor si,si
s1:                pop ds:;依次出栈,将字符串顺序保存到ds:中
                mov bl,30h
                add ds:,bl;数值转换为对应ASCII码
                inc si
                loop s1
                mov ds:,cx;将0保存到字符串结尾
                pop cx
                ret

show_str:;输出字符串子程序
                push ax
                push es
                mov ax,0b800h
                mov es,ax
                mov al,160
                mul dh
                mov bx,ax
                mov al,2
                mul dl
                add bx,ax               
                mov ah,cl
                xor cx,cx
s2:                mov cl,ds:
                jcxz ok2
                mov al,cl
                mov es:,ax
                inc si
                add bx,2
                jmp short s2
ok2:        pop es
                pop ax
                ret
               
code ends
end start

yundi 发表于 2016-4-5 17:02:21

ret                 用栈中数据修改ip        相当于 pop ip
retf                用栈中数据修改cs和ip        相当于 pop cs , pop ip



call                将当前ip 或 cs,ip入栈,然后跳转
1.    call 标号                                        相当于 push ip , jmp near ptr 标号
2.    call far ptr 标号                                相当于 push ip , jmp far ptr 标号
3.    call 16位reg                                相当于 push ip , jmp 16位reg
4.    call word ptr 内存单元地址        相当于 push ip , jmp word ptr 内存单元地址(2字节)
5.    call dword ptr 内存单元地址        相当于 push cs , push ip , jmp dword ptr 内存单元地址(4字节)
页: [1]
查看完整版本: 第十章检测实验及笔记