汇编语言——[bx]和loop指令
[bx]
由于在编译器中mov AX,[0]指令会被编译器认为是mov AX,0所以引入[bx]的概念
mov [bx],AX的意思是将(ds)*16+(bx)内存位置的值赋给AX
用法和之前的ds[address]一样
小Tips
1 ; [bx]的使用方法 2 mov ax,1000H 3 4 mov bx,2000H 5 6 mov ds,ax ; 将ds数据段寄存器赋值为2000H 7 8 mov [bx],ax ; 将ax寄存器的值赋给内存单元21000H位置 9 10 ; 其他方式 11 mov ax,ds:[0] ; 将内存单元20000H位置的值赋给ax
Loop指令(循环)
指令的格式是:loop 标号,CPU 执行loop指令的时候,要进行两步操作:
① (cx)=(cx)-1;
② 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
通常我们用loop指令来实现循环功能,cx 中存放循环次数。
示例:使用程序来计算211
1 assume cs:code 2 code segment 3 start:mov ax,2 4 mov cx,11 ; 设定循环次数为11 5 s: add ax,ax ; 每次循环执行的操作,每次执行的时候使cx-1 6 loop s ; 验证cx的值是否为0,为0执行下面的程序,否则跳回s(s可以为任意字符串)执行 7 mov ax,4c00h ; 程序返回 8 int 21h 9 code ends ; 代码段结束 10 end start
示例2:用加法计算123 x236 ,结果存在ax 中。
1 assume cs:xinge ; 定位代码段, 2 xinge segment ; 代码段可以为任意名字 3 start:mov ax,0 4 mov cx,123 5 jiaxin: 6 add ax,236 ; 要循环的操作 7 loop jiaxin 8 mov ax,4c00h 9 int 21h 10 code ends 11 end xinge
loop和[bx]的联合应用
思考:计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。
先看一个错的:错误原因,只定义了dl++,溢出不进位
1 assume cs:code 2 code segment 3 start: mov ax,0ffffH ; 编译器不支持字母开头的 4 mov ds,ax 5 mov bx,0 6 mov dl,0 7 mov dh,0 8 mov cx,12 9 10 s:add dl,[bx] 11 inc bx 12 loop s 13 14 mov ax,4c00H 15 int 21 16 code ends 17 end start
正确的
1 assume cs:code 2 code segment 3 start: mov ax,0ffffH ; 编译器不支持字母开头的 4 mov ds,ax 5 mov bx,0 6 mov dx,0 7 mov cx,12 8 9 s:mov al,[bx] ; 为低位赋值 10 mov ah,0 11 add dx,ax ; 用16位的相加,这样不会溢出 12 inc bx 13 loop s 14 15 mov ax,4c00H 16 int 21 17 code ends 18 end start
段前缀
出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”或“es:”,在汇编语言中称为段前缀。
段前缀的使用:
示例:将内存ffff:0~ffff:b段元中的数据拷贝到 0:200~0:20b单元中。
方法一:不断地修改ds的值,然后赋值
方法二:使用段前缀es:(es是多余段寄存器),这样可以省去不断地换ds的值
1 assume cs:code 2 code segment 3 mov cx,40H ; 循环次数,3F+1 4 mov ax,0 5 mov ds,ax 6 mov bx,200H 7 mov dx,0 8 s: 9 mov [bx],dx 10 inc dx 11 loop s 12 13 mov ax,4c00H 14 int 21H 15 code ends 16 end
1 assume cs:code 2 code segment 3 mov cx,40H 4 mov ax,20 ; 另段地址改为20 5 mov ds,ax 6 mov bx,0 ; bx就可以从0开始,和要推进内存单元的值一样了 7 s: 8 mov ds:[bx],bx 9 inc bx 10 loop s 11 12 mov ax,4c00H 13 int 21H 14 code ends 15 end