实验五 看看大佬的地方:https://www.cnblogs.com/kwcymino/p/10006595.html
利用doxbox
1.利用debug加载、跟踪程序
(1)先利用r命令来查看各个寄存器的值
(2)从cx中可知道程序的长度,用cx中的值减去20h(数据段和栈段已分配的空间)得到代码段的长度,用u命令精确反汇编
(3)先执行到000D之前,看看ds是否已成功指向数据段 -g:直接执行程序
(4)从上图可以看到ds已指向数据段,然后我们接着执行到程序返回前,即到001D之前,再查看一次数据段的内容
(5)从上图可以看到,数据段没有发生变化
2.书上的问题解答:
(1)程序返回前,data段中的数据为 23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09
(2)程序返回前,CS=076C,SS=076B,DS=076A
(3)设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1
-----也可以一直利用-t指令执行完程序。再利用-r查看状态
-----如果直接-g的话 出来的是 再利用-r查看状态反倒回到最开始的状态了
第二题:
1.利用debug加载、跟踪程序
(1)先利用r命令查看各个寄存器的值
(2)从上图的cx我们可以看到,cx的值与任务一的一样。虽然任务二只定义了两个字数据的数据段和两个字型数据当栈空间,但实际上在内存分配上还是给它们16个字节的空间,于是我用u命令精确反汇编一下
(3)再用g命令执行到000D以前,看看ds是否指向数据段data
(4)从上图看出ds已指向数据段data,再执行到程序返回前,看看数据段data的变化
(5)从上图看出,数据段没有变化
2.书上问题的解答:
(1)程序返回前,data段中的数据为 23 01 56 04
(2)程序返回前,CS=076C,SS=076B,DS=076A
(3)设程序加载后,code段的段地址为X,则code段的段地址为X-2,stack段的段地址为X-1
(4)对于如下定义的段,若段中的数据占N个字节,则程序加载后,该段实际占有的空间为((N+15)/16)*16(即数据的分配是以16个字节为单位的)
name segment : name ends
对于第四问的讲解:
因为每个段都是以16字节来对齐的,但是最大不能超过64KB 。这也就是说,如果你的段数据在16字节内,一样会被当做一个字节段来算,就是16字节。 要是大于16字节呢,那么如果多出就算是1个字节,因为已经超过一个16字节,多出来的1个字节 也得有一个字节段的容量来存储它,所以这时得占两个字节段,就是32字节,以此类推!
---
/ 这个符号是取整
N分为被16整除和不被16整除。
当N被16整除时: 占有的空间为(N/16)*16
当N不被16整除时: 占有的空间为(N/16+1)*16,N/16得出的是可以整除的部分,还有一个余数,余数肯定小于16,加上一个16。
两种情况总结成一个通用的公式:((N+15)/16)*16
解释了为啥:任务二cx的值与任务一的一样,明明定义少了。
第三题 看链接即可
2.书上问题的解答:
(1)程序返回前,data段中的数据为 23 01 56 04
(2)程序返回前,CS=076A,SS=076E,DS=076D
(3)设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4
第四题??
第五题:
我主要麻烦在不会-u-g的使用 只能-t
第六题
实验四
(1)编程,向内存0:200~0:23f依次传送数据0~63.
assume cs:code code segment mov ax,0020h mov ds,ax mov bx,0 mov cx,64 s:mov [bx],bx ;[bx]是省略后的物理地址 而后面就是个立即数 inc bx loop s mov ax,4c00h int 21h code ends end
2. 向内存0:200H~0:23fH依次传送数据0~63(3FH),9条命令的程序的简化版本(不包括伪代码)
(3)程序功能是将"mov ax,4c00h"之前的指令复制到内存0:200处,补全程序:
关于这两个地方的解释
1. https://www.cnblogs.com/kwcymino/p/9960424.html
2. mov ax,4c00h这个的地址:指令是存放在CS段内(此处写为CODE也是对的,因为都指向一个区域)/ 这应该存放的是该程序的段地址
3.debug查看程序代码总长度
;只写关键代码 ;每次复制单字节数据,并通过al中转 ;程序入口为cs:0(ip=0),所以第一空处传递段地址为cs ;接下来需要确定循环次数,即mov ax,4c00h之前的代码长度 ;而程序总代码长度可通过debug加载后通过u命令看出 ;先将第二空位随便设为1,加载后观察mov ax,4c00h之前代码为0000~0016h,总长度为23.使用debug调试一个EXE文件时候,使用r命令查看寄存器状态,其中cx寄存器的值(初始值)就是该程序代码的大小(按照字节数)。我们可以通过运行debug程序来调试生成的EXE文件,前提你先将CX寄存器赋个值。侧面验证CX寄存器的另一个作用。
根据cx寄存器,可知cx为1cH,因为在载入程序时,cx保存程序的长度,减去5是为减去mov ax,4c00h和int 21h的长度。所以,001cH-0005H=23 个
所以 cx 寄存器赋值为 17H。
实验八
分析程序,在运行前思考:这个程序是否能够正确返回?
运行之后再思考:为什么是这种结果?
通过这个程序加深对相关内容的理解。
assueme cs:codesg codesg segment mov ax,4c00h int 21h start: mov ax,0 s: nop nop mov di,offset s mov si,offset s2 mov ax,cs:[si] mov cs:[di],ax s0: jmp short s s1: mov ax,0 int 21h mov ax,0 s2: jmp short s1 nop codesg ends end start
CPU在执行jmp短指令的时候并不需要转移的目的地址,而包含的是转移的位移。这个位移,是编译器根据汇编指令中的“标号”计算出来的。
实验10
https://blog.csdn.net/XHS_12302/article/details/52056350
1. 显示字符串
assume cs:code data segment db 'Welcome to masm!',0 data ends code segment start: mov dh,8 mov dl,3 mov cl,2 mov ax,data mov ds,ax mov si,0 call show_str mov ax,4c00h int 21h show_str: push dx push cx push ds push si mov ax,0b800h mov es,ax mov al,160 mul dh mov bx,ax mov al,2 mul dl add bx,ax mov al,cl s: mov cl,[si] jcxz ok mov dx,[si] mov es:[bx],dx mov es:[bx+1],al inc si add bx,2 loop s ok: pop si pop ds pop cx pop dx ret code ends end start
2. 解决除法溢出的问题
assume cs:code code segment start:mov ax,4240h mov dx,000fh mov cx,0Ah call divdw mov ax,4c00H int 21h divdw: push ax mov ax,dx mov dx,0 div cx mov bx,ax pop ax div cx mov cx,dx mov dx,bx ret code ends end start
3.数值显示
assume cs:code
data segment
db 16 dup(0)
data ends
code segment
start:mov ax,12666
mov bx,data
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4c00h
int 21h
dtoc:
mov cx,ax ;17
jcxz bk
push ax
mov al,ah
mov ah,0
mov bl,10
div bl
mov cl,al
mov ch,ah
pop ax
mov ah,ch
div bl
mov dl,ah
mov dh,0
push dx
mov ah,cl
jmp short dtoc ;29
bk:pop ax
add ax,30h
mov [si],al
pop ax
add ax,30h
mov [si+1],al
pop ax
add ax,30h
mov [si+2],al
pop ax
add ax,30h
mov [si+3],al ;44
pop ax
add ax,30h
mov [si+4],al
mov byte ptr [si+5],0
ret
show_str:
mov si,0
mov ax,0b800h
mov es,ax
mov al,160
mul dh
mov bx,ax
mov al,2
mul dl
add bx,ax
mov al,cl
s: mov cl,[si]
jcxz ok
mov dx,[si]
mov es:[bx],dx
mov es:[bx+1],al
inc si
add bx,2
loop s
ok: ret
code ends
end start
实验七
si di 相当于指针
Nop指令是空指令 什么都不干 占存储空间 1个nop占一字节