laocaiye 发表于 7 天前

本例中or dl ,30h的意图

下面的例子是在给定字符串中查找某个字符,如果找到显示字符相对于字符串的首地址的偏移位置,如果未找到,就显示'N'。
但是我没看懂第22行“or dl,30”这行代码的意图,因为当查找位置大于10时,实际效果是字符转换。

data segment
string        db        'THIS IS A STRING'
count equ $-string
data ends

assume cs:code,ds:data,es:data
code segment

start:        mov ax,data
                mov ds,ax
                mov es,ax
                lea di,offset string
                mov al,'R'
                mov cx,count
                cld
                repne scasb
                jz found
                mov dl,'N'
                jmp display
found:        dec di
                mov dx,di
                or dl,30h
display:mov ah,02h
                int 21h
                mov ah,4ch
                int 21h
               
code ends
end start
               

jackz007 发表于 7 天前

本帖最后由 jackz007 于 2025-3-28 18:55 编辑

                or dl,30h
         这一句的作用是把 dl 寄存器中的数字变成对应的文本字符以便利用 DOS 的 AH=02 功能在屏幕上进行显示。例如,dl = 00h,or dl , 30h 后,dl = 30h = '0',再例如,dl = 09h,or dl , 30h 后,dl = 39h = '9' ,这个操作会把数字 0、9 分别变成对应的字符 '0' 和 '9'。
         但是,本例存在一个问题,那就是字符 'R' 的偏移为十进制 12,也就是说,dl 的值是 0ch,超出了十进制数字 9,是个十进制的两位数(12),就不可以直接 or dl , 30h 了,必须对相关的代码进行修改。
assume cs:code,ds:data,es:data
stack segment stack
            db 400h dup(00)
stack ends
data segment
string      db      'THIS IS A STRING'
count = $ - string
data ends
code segment
start:      mov ax,data
            mov ds,ax
            mov es,ax
            mov di,offset string      ; 这里应该用 mov 指令
            mov al,'R'
            mov cx,count
            cld
            repne scasb
            jz found
            mov dl,'N'
            jmp display
found:      dec di
            mov dx,di
            cmp dx,0ah                ; 判定偏移是否小于十进制 10
            jb x01                  ; 是则跳走
            mov ax,dx               ; 准备除法操作,被除数赋值
            mov cl,0ah                ; 准备除法操作,除数赋值
            div cl                  ; ax 除以 0ah
            mov dx,ax               ; dl 是商,dh 是余数
            add dl,30h                ; 把商由数字变成对应的字符
            mov ah,02h                ; 调用 DOS 功能进行屏幕显示
            int 21h                   ; 调用 DOS 功能进行屏幕显示
            mov dl,dh               ; 准备显示余数
x01:          add dl,30h
display:      mov ah,02h
            int 21h
            mov ah,4ch
            int 21h
code ends
end start

laocaiye 发表于 7 天前

这是网上一篇教学字符串处理汇编指令文章中的例题,不明白作者怎么没考虑偏移大于9的情况,还一位or dl,30h有其他意思。

FishC 发表于 前天 20:52

关于 OR DL,30H 的解释:

这个指令的作用是将数字转换为对应的ASCII字符。具体分析如下:

当找到字符时:
1. DEC DI 修正偏移量(SCASB会使DI多+1)
2. MOV DX,DI 获取偏移地址(假设偏移量 ≤ 255,此时DL=偏移量)
3. OR DL,30H 将数字转换为ASCII字符:
   - 数字 0 → 30H → '0'
   - 数字 5 → 35H → '5'
   - 数字 10 → 0AH → 0AH OR 30H = 3AH → ':'(这里存在逻辑错误!)

代码缺陷:
当偏移量 ≥10时(即需要显示两位数字时),这个简单转换会失效。正确做法应实现十进制数值转换(比如用DIV指令拆分十位和个位)。

修正建议:

; 以偏移量15为例的正确转换方法:
found:dec di
      mov ax,di       ; 获取偏移量
      mov bl,10
      div bl          ; AH=个位,AL=十位
      add ax,3030h    ; 同时转换十位和个位为ASCII
      mov dx,ax      ; DH=十位字符,DL=个位字符
      ; 需要分别输出两个字符

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 本例中or dl ,30h的意图