8086汇编学习笔记09

处理字符数据

系列文章

DEC、AND和OR指令

DEC指令(自减指令)
格式:
DEC container
用途:
container 对应的寄存器或存储空间中的值减少1。

这个指令同样比 SUB 指令的执行速度快,占用空间小。

对于每个位,只有两个运算对象中相应的位都为 1 时,结果才为 1(以逻辑方面看,只有当两个位都为真时,结果才为真)。

对于每个位,如果两个运算对象中相应的位有一个为 1 ,结果就为 1(从逻辑方面看,如果两个运算对象中至少有一个位为真,那么结果为真)。

AND指令(按位与指令)
格式:
AND container , value
用途:
container 对应的寄存器或存储空间中的值与 value 进行按位与运算,并将得到的结果存放到 container 中。

通过按位与指令可以将操作对象相应位设置为0,其余位不变(原理:任意位与1的与结果不变,与0的与结果为0)。

AL 寄存器第0位设置为0的指令是:AND al, 11111110B
AL 寄存器第2位设置为0的指令是:AND al, 11111011B
AL 寄存器最高位设置为0的指令是:AND al, 01111111B

OR指令(按位或指令)
格式:
AND container , value
用途:
container 对应的寄存器或存储空间中的值与 value 进行按位或运算,并将得到的结果存放到 container 中。

通过按位或指令可以将操作对象相应位设置为1,其余位不变(原理:任意位或0的或结果不变,或1的与结果为1)。

AL 寄存器第0位设置为1的指令是:OR al, 11111110B
AL 寄存器第2位设置为1的指令是:OR al, 11111011B
AL 寄存器最高位设置为1的指令是:OR al, 01111111B

字符数据

计算机中,所有的信息都是二进制,而人能理解的信息是已经具有约定意义的字符

要把这些信息存储在计算机中,就要对其进行编码,将其转化为二进制信息进行存储。而计算机要将这些存储的信息显示出来,就要对其进行解码

如果编码和解码遵循同样的规则,就可以将人类能理解的信息存入计算机中,再从计算机中取出。

计算机系统中一种通用的编码方案ASCII编码。该编码下一个字符需要使用8位(一个字节)存储。字符和数值的对应关系见下图:

ASCII字符表

可以在汇编代码中使用关键字 db 伪指令定义一系列字节型数据(define byte),数据之间同样以逗号分隔

汇编程序中,以单引号对'…' ”的方式指明的数据是以字符的形式给出的,编译器将它们转化为对应的ASCII码。

可以利用以上两者配合在程序中定义一系列字符,例如:

db 'Hello'

这相当一定义一系列字节型数据“ db 48H, 65H, 6CH, 6CH, 6FH ”。


ASCII码大小写规律:大写字母ASCII码的第5位是0,小写字母的第5位是1
利用以上规律,无需判断即可将一个字符转换为大写或小写。

以下示例程序,将数据段中的第一串字符大写,将第二串字符小写:

assume cs: codes, ds: datas
datas segment
    db 'BaSiC'
    db 'AsciiCoDing'
datas ends
codes segment
start:
    mov ax, datas
    mov ds, ax
    mov bx, 0     ; set DS:BX to first char of 'BaSiC'
    mov cx, 5     ; switch 'BaSiC' 5 chars to lowercase
toupper:
    mov al, [bx]  ; fetch ASCII codes from DS:[BX]
    and al, 11011111B
    mov [bx], al  ; switch 5th bit to 0, to lowercase
    inc bx        ; next character
    loop toupper
    mov bx, 5
    mov cx, 11
tolower:          ; similar logic
    mov al, [bx]
    or al, 00100000B
    mov [bx], al
    inc bx
    loop tolower
    mov ax, 4c00h
    int 21h
codes ends
end start

定位内存地址

可以用“ [BX+n] ”的方式来表示一个内存单元,它的偏移地址为 (BX)+n

[BX+n] 也可以写成以下格式:

可以用这种形式来更加灵活地定位内存地址。

SIDI 是8086CPU中和 BX 功能相近的寄存器BX基址寄存器SI源变址寄存器DI目的变址寄存器
BX 可以分为两个8位寄存器 BHBL 使用,但是 SIDI 不能分为两个8位寄存器使用

SIDI 寄存器的用法类似。

可以用基址寄存器和变址寄存器配合表示一个内存单元

以上几种格式是相同的,它表示的偏移地址为 (BX)+(SI)


可以用基址寄存器、变址寄存器和常量配合,表示一个内存单元

以上几种格式都是相同的,它表示的偏移地址为 (BX)+(SI)+n

基址寄存器、变址寄存器和常量配合,可以为实现数组提供便利

目前一共出现了以下几种定位内存的方式:

  1. [n] 使用一个常量表示内存地址,可用于直接定位一个内存单元
  2. [BX] 用一个变量来表示内存地址,可用于动态定位内存单元
  3. [BX+n] 用一个变量和常量表示地址,可用于在一个起始的地址基础上用变量间接定位一个内存单元
  4. [BX+SI] 用两个变量定位内存地址
  5. [BX+SI+n] 用两个变量和一个常量表示地址

以下示例程序利用寄存器 BXSI 配合访问一段二维数组,将其中的小写字母修改为大写字母:

assume cs: codes, ds: datas
datas segment
    db '1. file         '
    db '2. open         '
    db '3. save         '
    db '4. exit         '
datas ends
codes segment
start:
    mov ax, datas
    mov ds, ax        ; DS to target segment
    mov bx, 0         ; BX handles each line
    mov dx, 4         ; DX records lines
cols:
    mov si, 3         ; SI handles each column
    mov cx, 4         ; CX records columns
rows:
    mov al, [bx][si]  ; \
    and al, 11011111B ;  } switch to upper
    mov [bx][si], al  ; /
    inc si            ; [BX+SI] to next char
    loop rows

    add bx, 16        ; to next string  
    mov cx, dx
    dec dx
    loop cols
    mov ax, 4c00h
    int 21h
codes ends
end start

程序使用寄存器 CXDX 当做变量使用,配合嵌套循环,实现对行和列的遍历。