汇编(一)

  最近在学习汇编语言程序设计,主要学习的CPU是intel的80X86。在学习的过程中,感觉到了汇编挺有意思的地方:它是一门比较低级的语言,用助记符的形式表示了每一条计算机指令,每条指令对应计算机硬件的一个具体操作。这就不同于高级语言的“高封装性”了,你需要的功能,都需要你自己去实现,而不再能够借助于某个框架或者某个库。这让我们能够体会另一种编程思想,同时也让我们对底层编程有了一定基本的了解,对高级语言的功能实现有了一定的认识。

  下面是在课堂是留下的一道题目,回来之后就自己打开电脑实现了。但是在实现的过程中,两分钟的代码,20分钟的查错。整个代码思路还是很简单的,但是我在实现的过程中,还是被一个细节整了个半死。

  题目:用汇编实现将一个字节变量x用二进制的形式显示在屏幕上。

  看到这个题目,我的思路立刻就来了:将变量x按位进行带进位左移,然后用带进位加与30H相加,这样就可以得到进位CF中的字符的ASCII码,再用int 21H调用系统调用就可以了。于是得到了下面的汇编代码:

stack segment stack
    db 2014 dup(?)
stack ends
data segment
num    dw 12H
data ends
code segment 'code'
    assume cs:code,ds:data,ss:stack
start:
    mov bx,num
    mov cx,16
again:
    rol bx,1
    mov dl,0H
    adc dl,30H
    mov ah,02H
    int 21H
    loop again
    mov ax,4c00H
    int 21H
code    ends
    end start

  运行该代码发现结果并不正确。于是调用debug进行调试发现,bx寄存器中的值并不是如同预期的12H,而是一个奇怪的数字。多次运行发现都是如此。为什么会出现这样的情况?为什么num中的值没有传送给bx?当我看到assume的时候,发现了可能存在的问题:段基地址可能出错了,导致了执行mov指令的时候并没有指向正确的num的地址。

  首先再次查看了ASSUME伪指令的作用:通知MASM用指定的段寄存器来寻找对应的逻辑段,即建立段寄存器与段之间的默认关系。代码assume cs:code,ds:data,ss:stack指明了代码段默认的段基地址是cs,数据段的段基地址是ds,堆栈段的段基地址是ss。但是在代码中我并没有给ds传值的过程,因此导致了使用mov bx,num指令时使用了ds中本来的随机分配的数,所以没有找到变量num,也就没有将num的值正确的传给bx寄存器。代码做了如下的修改后,终于得到了正确的结果

stack segment stack
    db 2014 dup(?)
stack ends
data segment
num    dw 12H
data ends
code segment 'code'
    assume cs:code,ds:data,ss:stack
start:
    mov ax,data
    mov ds,ax
    mov bx,num
    mov cx,16
again:
    rol bx,1
    mov dl,0H
    adc dl,30H
    mov ah,02H
    int 21H
    loop again
    mov ax,4c00H
    int 21H
code    ends
    end start

  分析,上面的代码主要就是增加了一个给ds传值的过程,此处注意不能直接给ds赋值,这样在使用num变量的时候,将自动从ds取得段基地址,再与偏移地址进行相“加”,得到num物理地址。

 

posted @ 2015-10-21 22:04  Num.Zero  阅读(783)  评论(0编辑  收藏  举报