问题 7.9

编程,将 datasg 段中每个单词的前4个字母改为大写字母。

assume cs:codesg, ds:datasg, ss:stacksg

stacksg segment
	dw 0, 0, 0, 0, 0, 0, 0, 0
stacksg ends

datasg segment
	db '1. display      '
	db '2. brows        '
	db '3. replace      '
	db '4. modify       '
datasg ends

codesg segment

start:
	; 此处补全代码
codesg ends

end start

代码补全如下

assume cs:codesg, ds:datasg, ss:stacksg

stacksg segment
	dw 0, 0, 0, 0, 0, 0, 0, 0
stacksg ends

datasg segment
	db '1. display      '
	db '2. brows        '
	db '3. replace      '
	db '4. modify       '
datasg ends

codesg segment

start:
	mov ax, datasg
	mov ds, ax
	
	mov ax, stacksg
	mov ss, ax
	mov sp, 16
	
	; 因为都是用每行的第 3 个字节开始,所以这里设置为 3
	mov bx, 3
	mov cx, 4
	
lp:
	push cx
	mov cx, 4
	
lp0:
	mov al, [bx]
	and al, 11011111B
	mov [bx], al
	inc bx
	loop lp0
	
	; 第一个内层循环结束后,实际上是完成了第一行的转换,此时 bx 值为 7。
	; 因为在进入 loop 指令前,bx 已经自增了一次变为了 4,而 cx 为 4
	; 的循环实际是运行 3 次,所以在进入 loop 指令后,bx 又自增了三次,
	; 进而得出,在一次内循环结束后,bx 值变为了 7。可以通过 add bx, 16 
	; 使得 bx 偏移到下一行,但是偏移变为了 23 = 7 + 16,而实际第二行应该由 19 开始
	; 所以这里需要加上 12 而不是 16
	add bx, 12
	pop cx
	loop lp 
	
	mov ax, 4c00h
	int 21h
	
codesg ends

end start

调试

对于上面的程序,保存到 7.asm 之后,使用 masm 将其编译链接为可执行文件 7.exe。然后使用自带的 Debug 程序进行调试

debug 7.exe

首先使用 r 命令看下各个寄存器的情况

-r
AX=0000  BX=0000  CX=0074  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B34  ES=0B34  SS=0B44  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 B8450B        MOV     AX,0B45

可以看到 cs 段地址为 0B49ip 的值为 0000,那么可以使用 u 命令看下内存中的汇编代码

-u 0b49:0
0B49:0000 B8450B        MOV     AX,0B45
0B49:0003 8ED8          MOV     DS,AX
0B49:0005 B8440B        MOV     AX,0B44
0B49:0008 8ED0          MOV     SS,AX
0B49:000A BC1000        MOV     SP,0010
0B49:000D BB0300        MOV     BX,0003
0B49:0010 B90400        MOV     CX,0004
0B49:0013 51            PUSH    CX
0B49:0014 B90400        MOV     CX,0004
0B49:0017 8A07          MOV     AL,[BX]
0B49:0019 24DF          AND     AL,DF
0B49:001B 43            INC     BX
0B49:001C E2F9          LOOP    0017
0B49:001E 83C30D        ADD     BX,+0D

对比自己的汇编源码,发现第一行由 mov ax, datasg 变为了 mov AX,0B45,有此可知,0B45 就是程序实际的 datasg 段地址。那么可以看下 datasg 目前的内存内容是不是符合自己的汇编代码

-d 0b45:0
0B45:0000  31 2E 20 64 69 73 70 6C-61 79 20 20 20 20 20 20   1. display
0B45:0010  32 2E 20 62 72 6F 77 73-20 20 20 20 20 20 20 20   2. brows
0B45:0020  33 2E 20 72 65 70 6C 61-63 65 20 20 20 20 20 20   3. replace
0B45:0030  34 2E 20 6D 6F 64 69 66-79 20 20 20 20 20 20 20   4. modify
0B45:0040  B8 45 0B 8E D8 B8 44 0B-8E D0 BC 10 00 BB 03 00   .E....D.........
0B45:0050  B9 04 00 51 B9 04 00 8A-07 24 DF 43 E2 F9 83 C3   ...Q.....$.C....
0B45:0060  0D 59 E2 EF 92 7C 3C 2E-C7 06 1E 92 3E 2B 2E C7   .Y...|<.....>+..
0B45:0070  06 20 92 3D 3B E8 83 09-73 13 B8 FF FF 53 26 8B   . .=;...s....S&.

通过左右边的 ascii 码显示的结果可知,目前内存中的 datasg 是符合自己的汇编代码的。现在只需要单步运行(命令 t)在进入到 loop 指令时,使用 p 命令跳过循环的细节(并不是跳过循环),看看最终的结果对不对。

最终的结果为

-d 0b45:0
0B45:0000  31 2E 20 44 49 53 50 6C-61 79 20 20 20 20 20 20   1. DISPlay
0B45:0010  32 2E 20 42 52 4F 57 73-20 20 20 20 20 20 20 20   2. BROWs
0B45:0020  33 2E 20 52 45 50 4C 61-63 65 20 20 20 20 20 20   3. REPLace
0B45:0030  34 2E 20 4D 4F 44 49 66-79 20 20 20 20 20 20 20   4. MODIfy
0B45:0040  B8 45 0B 8E D8 B8 44 0B-8E D0 BC 10 00 BB 03 00   .E....D.........
0B45:0050  B9 04 00 51 B9 04 00 8A-07 24 DF 88 07 43 E2 F7   ...Q.....$...C..
0B45:0060  83 C3 0C 59 E2 ED B8 00-4C CD 21 CC 3E 2B 2E C7   ...Y....L.!.>+..
0B45:0070  06 20 92 3D 3B E8 83 09-73 13 B8 FF FF 53 26 8B   . .=;...s....S&.
Posted on 2015-08-04 18:02  mconintet  阅读(262)  评论(0编辑  收藏  举报