lab5 编写调试具有多段的程序

(1)

代码:

  1. assume cs:code,ds:data,ss:stack
  2. data segment
  3. dw 0123h,0456h,0789h,0abch,0defh,0cbah,0987h
  4. data ends
  5. stack segment
  6. dw 0,0,0,0,0,0,0,0
  7. stack ends
  8. code segment
  9. start: mov ax,stack
  10. mov ss,ax
  11. mov sp,16
  12. mov ax,data
  13. mov ds,ax
  14. push ds:[0]
  15. push ds:[2]
  16. pop ds:[2]
  17. pop ds:[0]
  18. mov ax,4c00h
  19. int 21h
  20. code ends
  21. end start

image.png
上图是程序没有
image.pngds指的是整个代码块加载的地方
很好理解, PSP 会用 100H 的内存, 然后先是data段, 075a:100 也就是076a, 占 16个字节, 所以 stack 段 在 076a:0010 也就是 076b cs同理

可以看到, 程序中的三个段在物理上是连续的内存

(2)

代码:

  1. assume cs:code, ds:data, ss:stack
  2. data segment
  3. dw 0123h,0456h
  4. data ends
  5. stack segment
  6. dw 0,0
  7. stack ends
  8. code segment
  9. start: mov ax,stack
  10. mov ss,ax
  11. mov sp,16
  12. mov ax,data
  13. mov ds,ax
  14. push ds:[0]
  15. push ds:[2]
  16. pop ds:[2]
  17. pop ds:[0]
  18. mov ax,4c00h
  19. int 21h
  20. code ends
  21. end start

image.png
①data段中的数据没有发生变化
②cs = 076c
ss = 076b
ds = 076a
ds’’ = 075a
③ cs -2h
cs - 1h
④ 如果段中有n个字节, 则程序加载后, 该段的实际占有空间大小为
这道题里 data 和 stack 段明明只有 4 字节却分配了 16 字节的空间大小
所以分配的一定是 n 和 16的最小公倍数

(3)

代码:
image.png

  1. assume cs:code,ds:data,ss:stack
  2. code segment
  3. start: mov ax,stack
  4. mov ss, ax
  5. mov sp,16
  6. mov ax,data
  7. mov ds,ax
  8. push ds:[0]
  9. push ds:[2]
  10. pop ds:[2]
  11. pop ds:[0]
  12. mov ax,4c00h
  13. int 21h
  14. code ends
  15. data segment
  16. dw 0123h, 0456h
  17. data ends
  18. stack segment
  19. dw 0,0
  20. stack ends
  21. end

① 没变
② ds 076d
ss 076e
cs 076a
可以看到 这种代码下 cs 在物理地地址中在低地址, 并且大小是 32 字节 0020h

③ ds: cs + 2h
ss: cs + 3h

(4)

从第一个段开始 分别是 data data code
因为默认情况下 Cs 的值是 ds + 0010h

(5)

将a,b段的数据依次相加放到c段中, 这题不难, 但是我太菜了, 给我累坏了, 做了半小时
代码:

  1. assume cs:code
  2. a segment
  3. db 1,2,3,4,5,6,7,8
  4. a ends
  5. b segment
  6. db 1,2,3,4,5,6,7,8
  7. b ends
  8. c segment
  9. db 0,0,0,0,0,0,0,0
  10. c ends
  11. code segment
  12. start: mov ax,a
  13. mov ds,ax
  14. mov ax,b
  15. mov es,ax
  16. mov ax,c
  17. mov ss,ax
  18. mov bx,0
  19. mov cx,8
  20. s: mov al,ds:[bx]
  21. mov ss:[bx],al
  22. mov ah,es:[bx]
  23. add ss:[bx],ah
  24. inc bx
  25. loop s
  26. mov ax,4c00h
  27. int 21h
  28. code ends
  29. end start

image.png

这题小总结一下:
这里分别用 ds es ss 三个段寄存器 去存了 abc 三个段的值
然后需要注意的是, db 伪指令定义的数据大小是一字节
所以后面用 al ah 两个中间量去存 ds:[bx] 和 es:[bx] 里的字节对应的值
还有一个教训:
只要加法就去思考是不是会涉及到overflow
注意相加的两个数和要操作的数的大小(位上)
这道题做这么久, 明显看出我汇编水平的拉胯, 汇编程序太生疏了, 确实, 汇编从逻辑上确实比高级语言难操作的多

(6)

用push指令将a段中 的前8个字型数据, 逆序存储到b段中

  1. assume cs:code
  2. a segment
  3. dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
  4. a ends
  5. b segment
  6. dw 0,0,0,0,0,0,0,0
  7. b ends
  8. code segment
  9. start: mov ax,a
  10. mov ds,ax
  11. mov ax,b
  12. mov ss,ax
  13. mov sp,16
  14. mov cx,8
  15. mov bx,0
  16. s: push ds:[bx]
  17. inc bx
  18. inc bx
  19. loop s
  20. mov ax,4c00h
  21. int 21h
  22. code ends
  23. end start

image.png
这里记录两点:
bx加的时候注意是字为单位还是字节, 第一次 Bx只加了1 导致结果很怪
第二点, 为什么高位在低字节?
我想想
为了验证我先去未执行的 a段瞧瞧
image.png
看了之后我懂了, 我多少带点
在DOS的指令里从左往右是增高地址, 所以是正确的…