一、数据表示
- 数制 16进制H 2进制B
- 编码
- N位无符号整数范围0~pow(2,N)-1
- 补码:最高位为符号位,0正1负。负数补码:全取反再加一(算上符号位在内全取反)
- 字符编码——BCD 8421
- 压缩的BCD:一个字节表达两位BCD
- 非压缩的BCD:二进制八位仅用低四位表达一个BCD
- 字符编码——ASCII
- 标准ASC码用7位编码,有128个。
- 不可显示的控制符:前三十二个和最后一个
- 可显示和打印的字符:从20H开始的95个编码。
- A~Z: 41H~5AH
- a~z:61H~7AH
- 大写字母和小写字母相差20H
- 0~9:30H~39H
- 空格:20H
- 回车:0DH
- 换行:0AH
- 字符编码——Unicode 16位
二、常量表达
- 常数
- 十六进制常数若以字母开头,则要添加前导0.
- 字符和字符串
- 用单引号或双引号括起来的单个字符或多个字符,如果字符串中有单引号本身可以用双引号,反之亦然;或者直接用ASC码表示:单引号27H,双引号22H
- 符号常量
- 符号定义伪指令:EQU和=
- 格式:
- 符号名 equ 数值表达式
- 符号名 equ <字符串>
- 符号名 = 数值表达式
- 字符串只能用EQU
- 使用等价伪指令EQU给符号定义一个数值或者定义一个字符串,这个字符串可以是一条处理器指令:CALLDOS EQU <INT 21H>
- EQU用于数值等价时不能重复定义符号名,等号可以
-
COUNT EQU COUNT+64H ;× COUNT = COUNT+64H ;√
-
- 数值表达式
- 真值255和-1的机器代码都是FFH
- 128和-128都是80H
三、变量应用
- 变量
- 变量是程序运行中随之发生变化的结果,保存在可读可写的主存空间。
- 实质是主存单元的数据,因而可以改变。
- 变量表达主存数据,即存储器操作数。
- 变量定义
- 变量名 变量定义伪指令 初值表
- 变量名是用户标识符,表示首元素的逻辑地址
- 变量定义的伪指令有DB DW DD DF DQ DT
- ?表示初值不确定,DUP为复制操作符 格式:重复次数 DUP(重复参数)
- 字节量数据
- DB 8位
- 无符号整数0~255
- 补码表示的有符号整数:-128~+127
- 一个字符(ASC码值)
- 压缩的BCD码:0~99
- 非压缩的BCD码:0~9
- 字量数据
- DW 16位
- 16位数据含高低两个字节,占两个连续的字节存储单元
- Intel采用小端方式存储 低对低高对高
-
WVAR6 DW 3139H,3832H BVAR6 DB 39H,31H,32H,38H DB '$' MOV DX , MOFFSET WAR6 MOV AH,09H INT 21H
- 显示结果:91289128
- 存储:
存储单元 存储器地址 38H 0035(H) 32H 0034 31H 0033 39H 0032(L) 存储单元 存储器地址 38H 0039(H) 32H 0038 31H 0037 39H 0036(L)
-
- 双字量数据 略
- 变量定位
- 变量定义的存储空间:按照书写的先后顺序一个接着一个分配
- ORG 参数:控制存放的偏移地址
- 例:
ORG 100H;从偏移地址100H处安排
- 例:
- N字节数据起始于能被N整除的地址
- ALIGN N控制对齐N字节边界 EVEN语句指示对齐模2地址
- 例:
align 2;对齐2字节地址边界
-
org100H bvar1 db100 ;0100 64 align 2 wvar2 dw 100 ;0102 0064 even dvar3 dd ? ;0104 00000000
;1.起始地址本应该为0,使用org控制起始于100
;2.100下一个地址为101 使用align 2控制地址能整除2 故分配在102 - 顺序执行的指令之间不能使用align和even
- 例:
- 变量属性
- 地址属性:首个变量所在存储单元的逻辑地址(含有段基地址和偏移地址)
- 类型属性:变量定义的数据单位
- 地址操作符
-
-
操作符 作用 [] 将扩起的表达式作为存储器地址指针 $ 返回当前偏移地址 OFFSET 变量名 返回变量名所在段的偏移地址 SEG 变量名 返回段地址(高十六位)
-
-
bvar db 12h,34h ;0000 12 34 org $+10 array dw 1,2,3,4,5,6,7,8,9,10 ;000C 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A wvar dw 5678h,9abch ;0020 5678 9ABC arr_size = $-array ;0024 = 0022-000C = 0018 arr_len = arr_size/2 ;=000C mov al,bvar mov ah,bvar+1 mov bx,wvar[2] mov cx,arr_len mov dx,$ mov si,offset wvar mov di,[si] mov bp,wvar
- 类型操作符
-
操作符 作用 类型名 PTR 变量名 将变量名按照指定的类型使用 TYPE 变量名 返回一个字量的数值,表明变量名的类型 LENGTHOF 变量名 返回整个变量的数据项数(即元素数) SIZEOF 变量名 返回整个变量占用的字节数
-
四、数据寻址方式
指令的两个部分:操作码+操作数
操作码用助记符表示,如mov; 操作数为指令执行的参与者,需要通过地址指示。
数据寻址方式:通过地址查找数据(操作数)
- 立即数寻址
- 操作数紧跟操作码,是机器代码的一部分。
- 操作数从指令代码立即得到,即立即数。用常量的形式直接表达。
- 立即数寻址方式只用于源操作数,常用来给寄存器和存储单元赋值。
- 立即数没有类型,它的类型取决于另一个操作数的类型。
- 立即数寻址实例
mov al,12h ;十六进制常数 mov ah,'d' ;字符(ascii) labl: mov bx,-1 ;十进制负数 mov cx,const ;符号常量;const = 64 mov dx,const*4/type wvar ;表达式 mov si,offset bvar ;操作符(byte sizeof lengthof也属于立即数寻址) mov di,labl ;标号也有地址属性 也可以用offset mov bvar,01001100b ;二进制数 mov wvar+2,12h ;十六进制常数
- 寄存器寻址
- 使用寄存器名表示它的内容
- 绝大多数采用通用寄存器寻址(AX,BX,CX,DX,DI,SI,BP,SP)
- 部分指令支持专用寄存器,例如段寄存器
- 要注意两个操作数的类型需要匹配(位数相同)
- 存储器寻址
-
- 存储器的地址使用逻辑地址(段基地址+偏移地址)
- 段寄存器有默认的使用规则,在寻址存储器操作数时,段寄存器不用显式说明。
-
访问存储器方式 默认的段寄存器 可超越的段寄存器 偏移地址 读取指令 CS IP 堆栈操作 SS SP 一般的数据访问(下列除外) DS CS,ES,SS EA(有效地址) BP为基地址的数据访问 SS CS,ES,SS EA(有效地址) 串指令的源操作数 DS CS,ES,SS SI 串指令的目的操作数 ES DI - 偏移地址=有效地址
- 默认规定:
- DS数据段: [bx] [si] [di] [常数]
- SS堆栈段: [bp]
- 显示说明:使用段超越指令前缀 例: ds:[bp]
- 主存操作数常通过变量形式引用,一般不需要使用段超越前缀指令
- 偏移地址的组成:16位有效地址=基址寄存器+变址寄存器+位移量
- 基址寄存器BX,BP
- 变址寄存器SI,DI
- 位移量 8或16位有符号值
- 直接寻址
-
mov ax,count ;也可以表示为:mov ax,[count] ;假如操作系统为变量COUNT分配的有效地址是2000H ;则反汇编的指令形式为mov ax,ds:[2000H] ;再假设DS保存段地址为1492H ;则14920H+2000H=16920H ;将地址为16920H的内容传送给AX寄存器,高字节送给AH寄存器,低字节送给AL寄存器
- mov指令不支持两个操作数都是存储器操作数
-
- 寄存器间接寻址
- 有效地址存放在寄存器中(寄存器内容=偏移地址=有效地址)
- 用中括号扩起寄存器
- 可以使用BX、BP、SI和DI寄存器作为间接寻址寄存器
- 寄存器间接寻址没有说明存储单元类型
- 例子:
mov al,[bx] mov cx,[si] mov [di],dl mov word ptr [di],1394H ;最后一句的说明: ;寄存器间接寻址没有说明指向的存储单元是何种类型,如果另一个操作数也没有类型,例如立即数,则需要使用类型操作符PTR显式说明
- 设计寄存器间接寻址的主要目的之一是方便对数组的元素或字符串的字符进行操作。
- 值得一说的点:
mov di,si ;正确,支持两个操作数都是寄存器操作数 mov [di],[si] ;错误,加了[]后为存储器寻址 相当于存储单元
- 寄存器相对寻址
- 只有BX、BP、SI和DI可以用作寄存器相对寻址的寄存器
- 使用BX、SI、DI默认访问数据段数据,使用BP默认访问堆栈段数据;但是都可以使用段超越前缀指令改变访问的逻辑段
- 例:
mov si,[bx+4] ;也可以表示成:[4][bx]或4[bx] ;位移量:4 mov di,[bp-08h] ;也可以表达为[-08h][bp]但不能是:-08h[bp] ;位移量:-08H mov ax,count[si] ;也可以表达为[si+count]或[count][si] ;位移量:count ;eg212.asm 复制字符串 .model small .stack .data srcmsg db 'Try your best, why not.$' dstmsg db sizeof srcmsg dup(?) .code .startup mov cx,lengthof srcmsg ;CX=字符串字符个数 mov bx,0 ;EBX指向首个字符 again: mov al,srcmsg[bx] ;取源串一个字符送AL mov dstmsg[bx],al ;将AL传送给目的串 add bx,1 ;加1,指向下一个字符 loop again ;字符个数CX减1,不为0,则转到AGAIN标号处执行 mov dx,offset dstmsg ;显示目的字符串内容 mov ah,9 int 21h .exit end
- 基址变址寻址
- 基址寄存器:BX BP
- 变址寄存器:SI DI
- 使用BP默认访问堆栈段 其余默认访问数据段 可以使用段超越
- 例:
mov al,[bx+si] ;源操作数在数据段,也可以表示为:[bx][si] mov ax,[bp+di] ;源操作数在堆栈段,也可以表示为:[bp][di] mov ax,ds:[bp+si] ;源操作数在数据段,也可以表示为:ds:[bp][di]
- 相对基址变址寻址
- 基址寄存器:BX BP
- 变址寄存器:SI DI
- 使用BP默认访问堆栈段 其余默认访问数据段 可以使用段超越
- 例:
mov cx,[bx+si+4] ;源操作数也可以表示为:4[bx+si] mov ax,80h[bx+di] ;源操作数也可以表示为:80h[bx][di] mov dx,count[bp][di] ;源操作数也可以表示为:[bp+du+count]
- 允许每个部分都使用中括号名单时基址寄存器要写在变址寄存器之前
- 变量和变量名也可以不卸载中括号内,但是这种情况下中括号前和数字开头不能使用正号或者负号。
- 数据寻址的组合
- 立即数寻址imm
- 通用寄存器寻址reg
- 存储器操作数寻址mem
-
五、课后习题
2.1 (2)字符“F”和数值46H作为mov指令的源操作数有区别吗?
没区别。
(3)为什么可以把指令“MOV AX,(34+67H)*3”中的数值表达成是常量?
汇编程序在汇编过程中对数值表达式计算,得到一个确定的数值,故称数值表达式为常量。
(4)汇编语言为什么规定十六进制数若以A~F开头,需要在前面加个0?
与标识符区分,因为标识符要求为字母或特殊字符开头。
(7)为什么将查找操作数的方法称为数据"寻址"方式?
指令的操作数要通过存储器地址或IO地址才能找到数据本身,故称数据寻址方式
(8)为什么变量VAR在指令”MOV AX,VAR“中表达直接寻址?
变量名代表的是逻辑地址的值,VAR表达了变量在主存中的存储单元。
2.2 判断题
(1)对一个正整数,他的补码与无符号数的编码一样。
对。
(2)常用的BCD码为8421码,其中的8表示D3位的权重。
对。
(3)排序一般按照ASCII码大小,从小到大升序排列时,小字母排在大写字母之前。
错。a:61H A:41H
(4)用“DB”和“DW”定义变量,如果初值相同,则占用的存储空间也一样多。
错。DB占用1字节,DW占用2自结
(7)某个字变量存放于存储器地址0403H~0404H中,对齐了地址边界。
错。字变量为两字节数据,应该对齐于偶数地址。
(8)立即数寻址只会存在于源操作数中。
对。
(9)存储器寻址方式的操作数当然在主存了。
对。
(10)指令“MOV AX,VAR+2”与“MOV AX,VAR[2]”功能相同。
对
2.3 填空题
(1)计算机中有一个”01100001“编码,如果把它认为是无符号数,它是十进制数 97 ;如果认为他是BCD码,则表示真值 61 ;如果它是某个ASCII码,则代表字符 a 。
(2)C语言用”\n“表示让光标回到下一行首位,在汇编语言中需要输出两个控制字符:一个是回车,其ASCII码是 ODH(13) ,它将光标移动到当前所在行的首位;另一个是换行,其ASCII码是 OAH(10) ,它将光标移到下一行。
(3)定义字节变量的伪指令助记符是 DB ,获取变量名所具有的偏移地址的操作符是 OFFSET 。
(4)数据段有语句”H8843 DD 99008843H",代码段指令“MOV CX, WORD PTR H8843"执行后,CX= 8843H 。
(6)数据段有语句“AVC DB 1,2,3”,代码段指令“MOV CL,ABC+2”执行后,CL= 3 。
(7)除外设数据外的存储方式有三种,分别称为 立即数寻址 、 寄存器寻址 和 存储器寻址 。
(8)指令“MOV AX,OFFSET MSG”的目的操作数和源操作数分别采用 寄存器寻址 和 立即数寻址 。
(9)已知SI=04000H,BX=20H,指令“MOV AX,[BX+SI+8]"中访问的有效地址是 4028H 。
(10)用BX做基地址的指针,默认采用 DS 段寄存器指向的数据段;如果采用BP作为基地址指针,默认使用 SS 段寄存器指向堆栈段。
2.6 将下列压缩BCD码转换为十进制数:
(1)1001 0001 = 9 1
(2)1000 1001 = 8 9
(3) 0011 0110 = 3 6
(4) 1001 0000 = 9 0
2.7 将下列十进制数用8位二进制补码表示:
(1)0 =0000 0000
(2)127 =0111 1111
(3)-127 =1000 0001
(4)-57 =1100 0111
2.8 进行十六进制数的加减运算,并说明是否有进位或错位:
(1)1234H+7802H =8A36H
(2)F034H+5AB0H =4AE4H 前有进位,去掉
(3)C051H-12345H =0AEIDH 以字母开头要有前导零
(4)9876H-ABCDH =0ECA9H
2.10 设置一个数据段,按照如下要求定义变量或符号常量:
(1)my1b为字符串变量:Personal Computer
my1b db 'Personal Computer'
(2)my2b为用十进制表示的字节变量20
my2b db 20
(3)my3b为用十六进制数表示的字节变量20
my3b db 14h
(4)my4b为用二进制表示的字节变量20
my4b db 00010100b
(5)my5w为20个未赋值的字变量
my5w dw 20 dup(?)
(6)my6c为100的常量
my6c = 100
(7)my7c表示字符串:Personal Computer
my7c equ <Personal Computer>
2.11 定义常量NUM,其值为5,数据段中定义字数组变量DATALIST,它的头5个字单元中依次存放-10,2,5和4,最后一个单元处置不确定
NUM = 5
DATALIST DW -10,2,5,4,?
2.13写出每条传送指令执行后寄存器AX的内容:
org 100h varw dw 1234h,5678h varb db 3,4 vard dd 12345678h buff db 10dup(?) mess db 'hello' mov ax,offset mess ;ax=100h+(2*2+2+4+10)=100+14=114h mov ax,type buff+type mess+type vard ;1+1+4=6 mov ax,sizeof varw+sizeof buff+sizeof mess ;2*2+10+5=19=13h mov ax,lengthof varw+lengthof vard ;2+1=3
2.15 数据段有如下定义,8086处理器将以小段方式保存主存:
var dd 12345678h
现以字节为单位按地址从低到高的顺序,写出这个变量内容,并说明如下指令的执行结果:
mov bx, word ptr var ;bx=5678h mov cx, word ptr var+2 ;cx=1234h mov dl, byte ptr var ;dl=78h mov dh, byte ptr var+3 ;dh=12h
2.17 说明下列指令中源操作数的寻址方式? 假设VARW是一个字变量。
mov dx, 1234h ;立即数寻址 mov dx, varw ;直接寻址 mov dx, bx ;寄存器寻址 mov dx, [bx] ;寄存器间接寻址 mov dx, [bx+1234h] ;寄存器相对寻址 mov dx, varw[bx] ;寄存器相对寻址 mov dx, [bx+di] ;基址变址寻址 mov dx, [bx+si+1234h] ;相对基址变址寻址