汇编语言:知识点拾遗

汇编语言:知识点拾遗

前言

读王爽的书已经有一段时间了,马上就要学习有关“中断”的知识了。在继续学习之前,我想把一些我感觉比较有意思的小细节,小技巧总结一下。文章不长,如果以后有新的收获,我会把这一系列继续写下去。

大小写字转换的技巧

一般来说,要想实现大小写字母的转换,有两种基本思路。

  1. 根据大小写字母在ascii表中的相对位置进行转换
  2. 根据字母在字母表中相对于首字母a的位置进行转换

第一种思路:
如果字母为大写字母,小写字母 = 大写字母 + 20H
如果字母为小写字母,大写字母 = 小写字母 - 20H

第二种思路:
如果字母为大写字母,小写字母 = ‘a’ + 大写字母 - ‘A’
如果字母为小写字母,大写字母 = ‘A’ + 小写字母 - ‘a’

王爽的书中有提供了令一种方法:
假设当前字母在寄存器AL中
如果AL为大写字母,则and al,11011111B
如果AL为小写字母,则 or al,00100000B
此时AL中即为所要转换的结果。

为什么可以这样做呢?我下面给出一张表格,供大家验证。

大写十六进制二进制小写十六进制二进制
A 41H 01000001 a 61H 01100001
B 42H 01000010 b 62H 01100010
C 43H 01000011 c 63H 01100011
D 44H 01000100 d 64H 01100100
E 45H 01000101 e 65H 01100101
F 46H 01000110 f 66H 01100110

JMP、CALL、RET指令的机制

以下用s表示标号

  • jmp short s——依据位移修改IP进行段内短转移(8位位移)
  • jmp near ptr s——依据位移修改IP进行段内近转移(16位位移)
  • jmp far ptr s——段间远转移,使(CS) = s的段地址,(IP) = s的偏移地址
  • jmp 16位reg——使(IP) = (reg)
  • jmp word ptr 内存单元地址——使(IP) = (内存单元地址)
  • jmp dword ptr 内存单元地址——使(CS) = (内存单元地址+2),(IP) = (内存单元地址)

详细内容见原书。

我们可以用汇编语言(尽管不符合语法)去理解ret和call指令

  • ret——相当于pop IP
  • retf——相对于先pop IP,然后pop CS
  • call s——相当于先push IP,然后jmp near ptr s
  • call far ptr s——相当于先push CS,再push IP,最后jmp far ptr s
  • call 16位reg——相当于push IP,然后jmp reg(16位)
  • call word ptr 内存单元地址——相当于push IP,然后jmp word ptr 内存单元地址
  • call dword ptr 内存单元地址——相当于先push CS,再push IP,最后jmp dword ptr 内存单元地址

由于call与ret常常配合使用,所以之前我以为这两条指令必须成对出现(在设计子程序的时候)。汇编语言是相当自由的语言,当然没有这种约束,这些指令你想怎么用,你就怎么用,只不过它们的配合使用是一种“套路”罢了。
如果不熟悉call,ret的执行原理,在设计子程序的堆栈传参时,就会很难理解。
我在课堂上学习这两条指令的时候,老师完全没说堆栈的事,之后我发现有一个实验(输出一个集合的所有子集)是要用递归的技巧的,我当时就要骂人了,老师当时堆栈传参讲的不清不楚(说难听点,讲了和没讲是一样的),果断放弃这个选题,选了一个更简单的实验,但这样怎么体现出我认真的学习态度呢?(不要脸
后来学习了王爽的书,弄懂了这些原理,堆栈传参就很好理解了。

最后补充一点:

  • ret n——相当于pop IP,然后add sp,n

C语言中局部变量也在堆栈中存放。

标志位DF与串处理指令

这部分老师在课堂上是不讲的(不知道其他学校是怎么样的)。其实这部分很简单。
方向标志位DF

  • DF = 1,每次操作后inc si, inc di
  • DF = 2,每次操作后dec si, dec di

cld指令使DF=0,std指令DF =1

下面用汇编指令(不符合语法)来理解下面两条指令

movsb

功能:

mov         es:[di], byte ptr ds:[si]
;如果DF = 0
                inc si
                inc di
;如果DF = 1
                dec si
                dec di

movsw

功能:

mov         es:[di], word ptr ds:[si]
;如果DF = 0
                add     si,2
                add     di,2
;如果DF = 1
                sub      si,2
                sub      di,2

rep指令

rep指令常常和以上两条指令配合使用。举个例子:
rep movsb 相当于

s:      movsb
        loop  s    ;根据CX决定循环次数

小结

串传送指令的注意点

  • 传送的初始位置:ds : si
  • 传送的目的位置:es : di
  • 传送的长度: CX
  • 传递的方向: 标志为DF

其他注意事项

由于篇幅原因(其实就是懒得再写下去了),还有一些注意点就不详细讨论了。
比如:
- 除法指令的溢出问题
- 80X25彩色字符模式的显示缓冲区

总结

汇编语言是一门相当自由的语言,只要你有耐心,你可以用它完成好多事情。
这种感觉是在学习王爽的教材中体会得到。在此之前,我只是通过学校课堂大概了解了一下汇编语言,我甚至不知道数据段,代码段,堆栈段是可以通过自己修改段寄存器来“定义”的(就是蠢,没别的解释)。但这种自由也带来一种坏处,就是代码的可读性较差,核心代码往往被其他操作掩盖(比如中间值传递,传参,保护寄存器),因此看似很长的代码,实际实现的功能很简单(这让我怎么显摆),甚至昨天刚写的代码,第二天居然读不懂了(好吧,我只是因为懒,没写注释,但不管怎么说,汇编就是难读!)。
但不管怎么说汇编还是很有用的。下面就用王爽书中的实验11——编写子程序,结束这篇博文。(我怎么还没写注释!反正没有老师看,偷个懒啦)

assume      cs:codesg

datasg      segment
    db 'Beginner`s All-purpose Symbolic Instruction Code.',0
datasg      ends

codesg      segment

main:       mov     ax,datasg
            mov     ds,ax
            mov     si,0
            call    letterc

            mov     ax,4c00h
            int     21h
;-----------------------------------------------------------
;proc_name:     letterc
;function:      translate uppercase into lowercase in a string which ends with digit 0
;interface:     ds:si points to the first address of the string

letterc:            push    ax
                    push    si

    letterc_s:      mov     al,[si]
                    cmp     al,'a'
                    jb      letterc_next
                    cmp     al,'z'
                    ja      letterc_next
                    and     al,11011111b
                    mov     [si],al
    letterc_next:   inc     si
                    cmp     al,0
                    je      letterc_out
                    jmp     short letterc_s

    letterc_out:    pop     si
                    pop     ax
                    ret
;----------------------------------------------------------
codesg      ends

end   main
posted @ 2016-12-18 17:33  20155110wangyifan  阅读(156)  评论(0编辑  收藏  举报