汇编网首页登录博客注册
gsyangchao的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
友情链接

[2009-01-30 01:20] 第十章call和ret指令

检测点10.1

补全程序,实现从内存1000:0000处开始执行指令。

assume cs:code

stack segment
        db 16 dup (0)
stack ends

code segment

start:        
        mov ax,stack
        mov ss,ax
        mov sp,16
        mov ax,1000H
                ----------
        push ax
        mov ax,0000H
                ----------
        push ax
        retf

code ends
end start


检测点10.2
    
    下面的程序执行后,ax中的数值为多少?
内存地址        机器码                汇编指令
1000:0                b8 00 00        mov ax,0
1000:3                 e8 01 00        call s
1000:6                40                        inc ax
1000:7                58                        s:pop ax

答:执行完call s后IP变为0006,push IP 后pop ax,所以ax的值为0000 0006。


检测点10.3

    下面的程序执行后,ax中的数值为多少?
内存地址        机器码                         汇编指令
1000:0                b8 00 00                  mov ax,0
1000:3                 9A 09 00 00 10          call far ptr s
1000:8                40                               inc ax
1000:9                58                                 s:pop ax
                                                        add ax,ax
                                                          pop bx
                                                    add ax,bx

答:执行完call far ptr s后IP变为0008,push CS,push IP后
            pop ax      ;ax=0000 0008
        add ax,ax   ;ax=0000 0010
        pop bx      ;bx=0000 1000
         add ax,bx   ;ax=0000 1010


检测点10.4
    
    下面的程序执行后,ax中的数值为多少?
内存地址        机器码                汇编指令
1000:0                b8 00 00        mov ax,6
1000:2                 ff d0            call ax
1000:5                40                inc ax
1000:6                                mov bp,sp
                                add ax,[bp]

答:        mov ax,6        ;ax=0000 0006
        call ax                ;IP=0005 ; PUSH IP ; jmp ax ;
        mov bp,sp
        add ax,[bp]        ;也就是add ax,[sp];而[sp]=0000 0005
                        ;ax=0000 000B


检测点10.5

(1) 下面的程序执行后,ax中的数值为多少?(注意:用call指令的原理来分析,

不要在Debug中单步跟踪来验证你的结论。对于此程序,在Debug中单步跟踪的结

果,不能代表CPU的实际执行结果)

assume cs:code

stack segment
        dw 8 dup (0)
stack endsd

code segment

start:
        mov ax,stack                        
        mov ss,ax                        ;stack段段地址存入ss
        mov sp,16                        
        mov ds,ax                        ;stack段段地址存入ds
        mov ax,0                        ;将ax置0
        call word ptr ds:[0EH]                ;IP=下一条指令第一字节
                                          ;然后PUSH IP后sp=0EH
                                        ;jmp word ptr ds:[0EH]
        
        inc ax                                ;ax=ax+1=0000 0001
        inc ax                                ;ax=0000 0002
        inc ax                                ;ax=0000 0003

code ends
end start

(2)下面的程序执行后,ax和bx中的数值为多少?

assume cs:code

data segment
        dw 8 dup (0)
data ends

code segment

start:
        mov ax,data                        
        mov ss,ax
        mov sp,16                        ;data段段地址送入ss,置sp为10H
        mov word ptr ss:[0],offset s        ;将s段起始处偏移量送入ss:[0]
        mov ss:[2],cs                        ;code段段地址送入ss:[2]
        call dword ptr ss:[0]                ;IP='nop'指令第一字节
                                        ;PUSH CS后sp=0EH,ss:[0EH]=(CS)
                                        ;PUSH IP后sp=0CH,ss:[0CH]=(IP)
                                        ;(CS)不变,(IP)=s段指令第一字节
        nop                                

s:
        mov ax,offset s                        ;将s段起始处偏移量送入ax
        sub ax,ss:[0CH]                        ;用ax和ss:[0CH]相减,ax=0H
        mov bx,cs                        ;将code段段地址cs送入bx
        sub bx,ss:[0eH]                        ;用bx和ss:[0EH]相减,bx=0H

code ends
end start



实验10  编写子程序

1.显示字符串
名称:show_str
功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79),
      (cl)=颜色,ds:si指向字符串的首地址
返回:无

show_str:
        push ax
        push bx
        push cx
        push dx
        push si                        ;入栈,保护现场

        mov ax,0B800H
        mov es,ax                ;显示器缓冲区段地址
        mov si,0                ;si指向data段字符

        dec dh
        mov al,160
        mul dh                        ;(dh-1)*160                
        mov bx,ax
        
        dec dl
        mov al,2
        mul dl                        ;(dl-1)*2
        add bx,ax                ;(dh-1)*160+(dl-1)*2=对应显存起始地址

        mov ah,cl                        ;将颜色属性送入高位
change:
        mov cl,ds:[si]                        ;将要显示的字符送入cl中
        mov ch,0
        jcxz show_strok                        ;碰到符'0'结束
        mov al,cl                        ;将字符送入低位,整个信息在ax中
        mov es:[bx],ax                        ;存入显存
        
        inc si
        add bx,2
        jmp short change

show_strok:
        pop si
        pop dx
        pop cx
        pop bx
        pop ax
        ret        

2.解决除法溢出的问题
名称:divdw
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为

dword型。
参数:(ax)=dword型数据的低16位
      (dx)=dword型数据的高16位
      (cx)=除数
返回:(dx)=结果的高16位,(ax)=结果的低16位
      (cx)=余数

divdw:
        push si
        push di                ;保护现场
        
        mov si,ax        ;将X的低16位L存入si
        
        mov ax,dx        ;将X的高16位H存入ax
        mov dx,0        
        div cx                ;(H/N)故需要H的低16位在ax,高16位在dx
                        ;(ax)=int(H/N) (dx)=rem(H/N)

        mov di,ax        ;将int(H/N)存入di中

        mov ax,si        
        div cx                ;(ax)=[rem(H/N)*65536+L]/N的商,(dx)=其余数
                        
        mov cx,dx        ;将余数存入cx中
        mov dx,di        ;将int(H/N)作为商的高16位存入dx
                        ;即int(H/N)*65536
        pop di
        pop si
        ret


3.数值显示
名称:dtoc
功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
参数:(ax)=word型数据
      ds:si指向字符串的首地址
返回:无

dtoc:        
        push ax
        push cx
        push si
        push di
        push dx

        mov di,sp        ;将当前栈指针的值送入di保存
                        ;用来取数据时的是否取完

divide:
        mov dx,0        ;为防止溢出,进行16位除法
        mov cx,10        ;除数为10
        div cx                ;(dx)=rem(ax/10) (ax)=int(ax/10)
        
        push dx                ;将余数入栈

        mov cx,ax        ;将商移入cx用来判断是否求完
        jcxz convert        ;(cx)=0表示已求完,进行转换
                        
        jmp short divide        ;没有求完则,商作为下一次的被除数

convert:
        mov cx,di        ;将数据入栈前栈指针的值送入cx与当前栈指针比较
        sub cx,sp                
        jcxz dtocok        ;如果数据全部出栈,则convert完成,没完成继续出栈

        pop ax                ;余数仅为0~9所以可以用8位寄存器表示出来
        add al,30H        ;将余数加30H变为ASC码
        mov ds:[si],al        ;字符串送入首地址
        
        inc si
        jmp short convert

dtocok:        
        mov ds:[si],0
        pop dx
        pop di
        pop si
        pop cx
        pop ax
        ret

(1)各子程序均带入程序中测试正确。
(2)divide子程序中我用15266吧好像是,反正是挺大一个数执行后处了错,但不是除法溢出,好像是MS-DOS的保护措施,估计是子程序中没开辟栈空间,系统自动开辟的用的太都了就溢出了吧,与子程序本身没关,其他数据(比12666小的)显示正常。
(3)我个人觉得子程序这东西既然叫子程序,你里面所有用到的寄存器,除了要求返回的寄存器您可以在一开始不保存,其他寄存器都应该PUSH,保存起来,不能因为1个子程序就修改了某些寄存器的值。
(4)子程序,就应该老实一点,别人传了什么参数进来,功能是怎么返回的一定要明确,不能给了你SI是字符串首地址,你来个逆序输出。
评论次数(4)  |  浏览次数(1524)  |  类型(汇编作业) |  收藏此文  | 

[  younggay   发表于  2009-02-02 17:00  ]

ax的值为0000 0006
ax=0000 000B 
------
ax可是16位的,你这么一些,好像...

[  younggay   发表于  2009-02-02 17:03  ]

10.5的第2题
sub ax,ss:[0CH]            ;用ax和ss:[0CH]相减,ax=0H 
===================
这里的ax的值不对,ss:[0cH]中保存的是call指令下面的指令的ip地址,而s可是call后面的第二条指令哟,没看到那个nop么?

[  younggay   发表于  2009-02-02 17:07  ]

(2)divide子程序中我用15266吧好像是,反正是挺大一个数执行后处了错,但不是除法溢出,好像是MS-DOS的保护措施,估计是子程序中没开辟栈空间,系统自动开辟的用的太都了就溢出了吧,与子程序本身没关,其他数据(比12666小的)显示正常。
==============
我觉得应该是你程序的问题。再研究研究吧。即使处理32位的数据,该算法也应该没有问题的。

[  游客   发表于  2010-07-06 11:02  ]

下面的程序执行后,ax和bx中的数值为多少? (10.5的第二题)

AX的值应该为1   NOP指令占了一个字

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码