鱼C论坛

 找回密码
 立即注册
查看: 4594|回复: 3

[已解决]《汇编语言》10.12寄存器冲突的问题(2)将所有字符串大写,有两个疑惑,寻求帮助

[复制链接]
发表于 2021-1-7 14:47:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 rooaw 于 2021-1-7 14:51 编辑

整理了一下书上完整代码如下:

  1. assume cs:code

  2. data segment
  3.         db 'word', 0
  4.         db 'word', 0
  5.         db 'word', 0
  6.         db 'word', 0
  7. data ends

  8. code segment
  9. start:
  10.         mov ax, data
  11.         mov ds, ax
  12.         mov bx, 0                                ;ds:[bx]字符串地址

  13.         mov cx, 4                                ;四组字符串
  14.         s:      mov si, bx                       ;从第1个字符开始
  15.                 call capital                       ;capital用于将当前一组字符串改为大写
  16.                 add bx, 5                        ;到下一组字符串
  17.                 loop s

  18.                 mov ax, 4c00h
  19.                 int 21h

  20.         capital:      push cx                       ;cx表示循环到了第几组
  21.                         push si                        ;si表示当前组第几个字符

  22.                         change:     mov cl, [si]                                        ;字符存到cl
  23.                                         mov ch, 0                                                
  24.                                         jcxz ok                                               ;cx为0表示这组字符结束
  25.                                         and byte ptr [si], 11011111b                ;否则字符转为大写
  26.                                         inc si                                                  ;到下一个字符
  27.                                         jmp short change               

  28.                         ok:           pop si                                            
  29.                                         pop cx
  30.                                         ret                                                     ;跳转到s循环里add bx, 5指令

  31. code ends

  32. end start
复制代码


第一个疑惑是 si 寄存器为什么需要入栈(27行)?不管 pop si 后 si 的值为多少,都会回到循环开头被 bx 赋值(18行)不是吗?
第二个疑惑是 change 标号那段其实就是个循环,只是因为 cx 要被占用无法用来记循环次数,所以不好写成 loop,而是用的 jmp 转移?
最佳答案
2021-1-7 17:18:26
本帖最后由 jackz007 于 2021-1-7 17:30 编辑
  1.      assume ds:data , es:data , cs:code
  2. stack segment stack para 'stack'
  3.      dw 800h dup(00)
  4. stack ends

  5. data segment public para 'data'
  6.     msg1  db 'word' , 00
  7.     msg2  db 'word' , 00
  8.     msg3  db 'word' , 00
  9.     msg4  db 'word' , 00
  10. data ends

  11. code segment public para 'code'
  12. captal proc near
  13.         cmp al , 'a'
  14.         jb cap01
  15.         cmp al , 'z'
  16.         ja cap01
  17.         sub al , ' '
  18. cap01:  ret
  19. captal endp

  20. main proc far
  21.         mov ax,data
  22.         mov ds,ax
  23.         mov es,ax
  24.         mov bx,offset msg1 - 5
  25.         mov cx,4
  26.         cld
  27. m1:     add bx,5
  28.         mov si,bx
  29.         mov di,bx
  30. m2:     lodsb
  31.         or al,al
  32.         jz m3
  33.         call captal
  34.         stosb
  35.         jmp m2
  36. m3:     loop m1               
  37.         mov ax,04c00h
  38.         int 021h
  39. main endp
  40. code ends
  41. end main
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-1-7 16:31:15 | 显示全部楼层
问题1.
你说的没错, 在这程序中即使si不入栈也不会出错, 不过最好将子程序会用到的寄存器都事先保存, 以防止未来各种状况, 我猜作者是想表达这意思

问题2.
这里不用loop是因为要透过字符串后面的 '0' 来判断循环是否结束, 与cx是否被占用无关
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-1-7 17:18:26 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2021-1-7 17:30 编辑
  1.      assume ds:data , es:data , cs:code
  2. stack segment stack para 'stack'
  3.      dw 800h dup(00)
  4. stack ends

  5. data segment public para 'data'
  6.     msg1  db 'word' , 00
  7.     msg2  db 'word' , 00
  8.     msg3  db 'word' , 00
  9.     msg4  db 'word' , 00
  10. data ends

  11. code segment public para 'code'
  12. captal proc near
  13.         cmp al , 'a'
  14.         jb cap01
  15.         cmp al , 'z'
  16.         ja cap01
  17.         sub al , ' '
  18. cap01:  ret
  19. captal endp

  20. main proc far
  21.         mov ax,data
  22.         mov ds,ax
  23.         mov es,ax
  24.         mov bx,offset msg1 - 5
  25.         mov cx,4
  26.         cld
  27. m1:     add bx,5
  28.         mov si,bx
  29.         mov di,bx
  30. m2:     lodsb
  31.         or al,al
  32.         jz m3
  33.         call captal
  34.         stosb
  35.         jmp m2
  36. m3:     loop m1               
  37.         mov ax,04c00h
  38.         int 021h
  39. main endp
  40. code ends
  41. end main
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-12 15:29:03 | 显示全部楼层
咦,最佳答案不小心给错了楼
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-8 18:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表