代码如下:
assume cs:code, ds:data data segment db ‘Nuist‘ db 5 dup(2) data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start
运行结果如下图:
调试过程如下图:
将db 5 dup(2)改成db 2,3,4,5,6后,代码如下:
assume cs:code, ds:data data segment db ‘Nuist‘ db 2,3,4,5,6 data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start
运行结果如下图:
调试过程如下图:
源代码中line4的字节数据写入了B800:0F00后5个字的高位字节中,即写入了显存单元中决定色彩的字节,改变它们将改变现实内容的色彩。故该数值的作用为决定字符的色彩。
源代码如下:
assume cs:code, ds:data data segment db 23, 50, 66, 71, 35 data ends code segment start: mov ax,data mov ds,ax mov cx,5 mov si,0 mov bl,0ah s: mov al,ds:[si] mov ah,0 div bl add ah,030h add al,030h mov bx,ax mov ah,2 mov dl,bl int 21h mov dl,bh int 21h mov bl,0ah inc si loop s mov ah,4ch int 21h code ends end start
运行结果如下:
源代码如下:
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h data ends stack segment dw 0, 0, 0, 0, 0, 0, 0, 0 stack ends code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
使用debug执行至返回前,此时各寄存器状态如下图:
使用d命令查看数据段中数据,如下图:
故:
①data段中的数据为23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09
②程序返回前,cs=076C,ss=076B,ds=076A。
③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
源代码如下:
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h data ends stack segment dw 0, 0 stack ends code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
使用debug执行至返回前,此时各寄存器状态如下图:
使用d命令查看数据段中数据,如下图:
故:
①data段中的数据为23 01 56 04
②程序返回前,cs=076C,ss=076B,ds=076A。
③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
④如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为?N/16?*16。
源代码如下:
assume cs:code, ds:data, ss:stack code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends data segment dw 0123h, 0456h data ends stack segment dw 0,0 stack ends end start
使用debug执行至返回前,此时各寄存器状态如下图:
使用d命令查看数据段中数据,如下图:
故:
①data段中的数据为23 01 56 04
②程序返回前,cs=076A,ss=076E,ds=076D。
③设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4。
如果将“end start”改为“end”,则task5.exe依然可以正常运行,其它两个不能。这是由于task5.exe中段的排列顺序为代码段——数据段——栈段,加载入内存后CS:IP默认指向程序开头,即代码段开头,故能正常运行。其它两个程序中段的排列顺序为数据段——栈段——代码段,加载入内存后CS:IP默认指向程序开头,即数据段开头,CPU将会把数据段中的数据解释为指定运行,引发错误。
源代码如下:
assume cs:code, ds:a, ss:b ,es:c a segment db 1,2,3,4,5,6,7,8 a ends b segment db 1,2,3,4,5,6,7,8 b ends c segment ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称 db 8 dup(0) c ends code segment start: mov ax,a mov ds,ax mov ax,b mov ss,ax mov ax,c mov es,ax mov si,0 mov cx,8 s: mov al,ds:[si] add al,ss:[si] mov es:[si],al inc si loop s mov ah,4ch int 21h code ends end start
使用debug运行至返回前,查看逻辑段C中内容,如下图:
可见,程序实现了要求。
源代码如下:
assume cs:code, ds:a, ss:b a segment dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh a ends b segment dw 8 dup(0) b ends code segment start: mov ax,a mov ds,ax mov ax,b mov ss,ax mov sp,010h mov si,0 mov cx,8 s: push [si] add si,2 loop s mov ah,4ch int 21h code ends end start
使用debug运行至返回前,查看逻辑段B中内容,如下图:
可见,程序实现了要求。
在编写实验任务2的程序时,一开始,运行编写完成的程序后将会陷入死机无法退出,只能重启dosbox。使用debug单步执行发现执行除法指令后,CPU执行的下一条指令不再是预期的add ah,030h,而是??? [bx+si],且CS、IP等寄存器的数值均发生了变化。显然,这一命令是错误的,是死机的源头。查询资料发现,这是除法溢出导致的。检查代码后,发现原因为我将mov al,ds:[si] mov ah,0误写为mov ax,ds[si]。关于除法溢出的具体解释如下:
x86的除法指令正确执行是有条件的。这个条件是:被除数的高位寄存器数值,必须小于除数。如果数据不满足这样的条件,被除数的高位寄存器数值大于或者等于除数(相当于除法运算后产生的商会是个跟被除数大小一样的数值级别,但是实际上用来存放商的实际寄存器数值级别只有被除数的一半大小),就会产生除法溢出。此时,将会自动触发触发溢出中断。
通过该问题,我学到了x86汇编语言中并非语法检查无错误程序就能正常运行。部分指令的执行是有额外的限制条件的。
原文:https://www.cnblogs.com/SpeakLessPoiMore/p/14044672.html