迭代字符串(8086程序集)

时间:2015-10-26 11:24:34

标签: string assembly x86 x86-16 emu8086

好吧,我开始像一个月前开始学习8086汇编,直到现在我学习它没有太多问题,但现在我被困在字符串中。问题是如何在8086中迭代字符串并操纵字符?此外,我有一个任务,我的微处理器课程删除给定字符串中的所有'字符(我的代码中的字符串“proce'so'r”),然后比较新获得的字符串与第一个字符串,并检查它们是否相等。事情是我甚至不知道如何迭代它。这真的没有在课堂上解释,所以我在这里寻求帮助。这是我的代码到目前为止(仅用于字符串迭代和打印字符,它不起作用,不知道为什么):

data segment
 string db "proce'so'r"
ends

stack segment
    dw   128  dup(0)
ends

code segment
start:

    lea di, string
    mov cx, 10

    for:
        cmp cx, 0
        je end


        mov dl, [di]
        mov ah, 02h
        int 21h 

        inc di
        loop for     
    end:


mov ax, 4c00h
int 21h  

ends

end start

2 个答案:

答案 0 :(得分:0)

扩展我的评论:一个更有效的循环结构将是:

data segment
 string db "proce'so'r"
 stringlen equ $-string   ; subtract current string's address from current address
ends

start:

    mov ax, data
    mov ds, ax     ; Assuming rkhb is correct about segments

    lea   di, string
    mov   cx, stringlen   ; having the assembler generate this constant from the length of the string prevents bugs if you change the string

    ;; if stringlen can be zero:
     ;  test cx,cx
     ;  jz end

    ;; .labels are "local" and don't end up as symbols in the object file, and don't have to be unique across functions
    ;; emu8086 may not support them, and this Q is tagged as 8086, not just 16bit DOS on a modern CPU.
    print_loop:
        mov   dl, [di]
        mov   ah, 02h  ; If int21h doesn't clobber ah, this could be hoisted out of the loop.  IDK.
        int   21h 

        inc   di
        dec   cx
        jg   print_loop  ;  or jne
    end:

          ;  Or save a register (and the mov to initialize it) with
          ;   cmp  di, offset string+stringlen 
          ;   jb   print_loop

         ;; loop print_loop  ; or save instruction bytes, but slower on modern CPUs

mov ax, 4c00h
int 21h

处理字符串的一种更常见的方法是使用零字节终止它们。所以循环绑定将是test dl,dl / jnz,不需要计数器。

另外,请注意,使用si作为源指针并使用di作为dest指针是典型的。

您可以通过执行

来跳过某个字符来复制字符串
    mov   dl, [si]
    inc   si
    cmp   dl, '\''   ; or write the value as a hex constant instead of a character literal
    je  nocopy
     mov   [di], dl
     inc   di
nocopy:

作为循环的一部分。在循环开始时,你希望si指向输入字符串中的第一个字符,而di指向一个足以保存结果的缓冲区。要跳过的字符可以在寄存器中,而不是硬编码为cmp的直接操作数。

如果你真的想以现代CPU的速度为代价来节省代码字节,你可以使用字符串移动指令lodsb / stosb,除了它们加载到/存储来自{ {1}}。

答案 1 :(得分:0)

您需要初始化DS以使用定义的数据段。

完整解决方案:

DATA SEGMENT
 STRING DB "PROCE'SO'R"
ENDS

STACK SEGMENT
    DW   128  DUP(0)
ENDS

CODE SEGMENT
START:

    MOV AX,@DATA
    MOV DS,AX

    LEA DI, STRING
    MOV CX, 10H

    FOR:
        CMP CX, 0
        JE END

        MOV DL, [DI]
        MOV AH, 02H
        INT 21H 

        INC DI
        LOOP FOR     
    END:

MOV AX, 4C00H
INT 21H  

ENDS

END START

在开始之后注意以下内容:

    MOV AX,@DATA
    MOV DS,AX