簡體   English   中英

用於比較未給出正確 output 的字符串的匯編程序

[英]Assembly program to compare strings not giving correct output

我正在嘗試編寫一個匯編程序來比較兩個字符串並輸出它們是否相等,我試圖通過一一增加索引寄存器並比較字符來做到這一點。

但是我的代碼似乎有一個錯誤,因為我期待 output Equal

但實際的 output 是:

Equal
NotEqual

代碼:

%include "asm_io.inc"
segment .data
str1: db "ThisIsSomeString", 0
str2: db "ThisIsSomeString", 0
msg_eq: db "Equal", 10, 0
msg_neq: db "NotEqual", 10, 0

segment .text
        global  asm_main
asm_main:
    mov esi, str1
    mov edi, str2
    xor edx, edx              ; to clear edx for index addressing
loop:
    mov al, [esi + edx]
    mov bl, [edi + edx]
    inc edx
    cmp al, bl
    jne not_equal
    cmp al, 0                 ; check if we're at the end of string
        je equal
    jmp loop
not_equal:
    mov eax, 4                ; system call number (sys_write = 4)
    mov ebx, 1                ; stdout = 1
    mov ecx, msg_neq          ; message to print
    int 0x80                  ; issue a system call
    jmp exit
equal:
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_eq
    int 0x80
    jmp exit
exit:
    mov eax, 1                ; system call number (sys_exit = 1)
    mov ebx, 0                ; exit code
    int 0x80

您沒有為sys_write提供長度。 它需要寫入edx的字節數。 它並不關心您嘗試打印的字符串是一個以 nul 結尾的字符串。 您可以通過將您希望的消息長度保存到 output 來解決問題,例如

segment .data
str1: db "ThisIsSomeString", 0
str2: db "ThisIsSomeString", 0
msg_eq: db "Equal", 10, 0
len_eq   equ $ - msg_eq
msg_neq: db "NotEqual", 10, 0
len_neq  equ $ - msg_neq

nasm中, $是當前語句之前的當前堆棧地址。 因此,只需在聲明字符串的位置使用$ - string_before ,就可以保存長度以供以后與sys_write一起使用,例如

segment .data
str1: db "ThisIsSomeString", 0
str2: db "ThisIsSomeString", 0
msg_eq: db "Equal", 10, 0
len_eq   equ $ - msg_eq
msg_neq: db "NotEqual", 10, 0
len_neq  equ $ - msg_neq

segment .text
        global  _start
_start:

    mov esi, str1
    mov edi, str2
    xor edx, edx              ; to clear edx for index addressing
loop:
    mov al, [esi + edx]
    mov bl, [edi + edx]
    inc edx
    cmp al, bl
    jne not_equal
    cmp al, 0                 ; check if we're at the end of string
        je equal
    jmp loop
not_equal:
    mov eax, 4                ; system call number (sys_write = 4)
    mov ebx, 1                ; stdout = 1
    mov ecx, msg_neq          ; message to print
    mov edx, len_neq          ; length in edx
    int 0x80                  ; issue a system call
    jmp exit
equal:
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_eq
    mov edx, len_eq           ; length in edx
    int 0x80
    jmp exit
exit:
    mov eax, 1                ; system call number (sys_exit = 1)
    mov ebx, 0                ; exit code
    int 0x80

注意:不需要您的%include "asm_io.inc"語句)

另請注意,我已將您的asm_main替換為_start以在我的機器上編譯和運行,只需根據需要將其更改回來。

示例 Output

$ ./bin/strcmp32
Equal

作為大衛 C。 Rankin 說, sys_write系統調用不像 C 語言中的puts工作——它不會寫出以 NUL 結尾的字符串。 相反,它要求你明確告訴它要寫多少個字符。 它在EDX寄存器中接受此參數。 當您在equal調用sys_write時, EDX將等於正在檢查的字符串中的字符數。 由於測試字符串的長度為 16 個字符,並且您已告訴sys_write從地址msg_eq開始打印字符,因此它會打印以下字符:

E
q
u
a
l
10
0
N
o
t
E
q
u
a
l
10

這正是你所看到的! 這里的關鍵點是匯編器將msg_eq放在msg_neq之后,因此當sys_write運行到msq_eq的末尾時,它會繼續到msg_neq

我建議按如下方式修改您的代碼:

%include "asm_io.inc"
segment .data
str1:    db "ThisIsSomeString", 0
str2:    db "ThisIsSomeString", 0
msg_eq:  db "Equal", 10, 0
msg_neq: db "NotEqual", 10, 0

segment .text
global  asm_main
asm_main:
    mov  esi, str1
    mov  edi, str2
    xor  edx, edx              ; to clear edx for index addressing
    ; Set up output assuming the strings are not equal:
    mov  ecx, msg_neq          ; message to print
    mov  edx, 9                ; number of characters to print (length of string)
loop:
    mov  al, [esi + edx]
    mov  bl, [edi + edx]
    inc  edx
    cmp  al, bl
    jne  print                 ; if string is not equal, skip straight to print
    test al, al                ; check if we're at the end of string
    jne  loop
    ; The strings were actually equal, so change output setup:
    mov  ecx, msg_eq           ; message to print
    mov  edx, 6                ; number of characters to print (length of string)
print:
    mov  eax, 4                ; system call number (sys_write = 4)
    mov  ebx, 1                ; stdout = 1
    int  0x80                  ; issue a system call
exit:
    mov  eax, 1                ; system call number (sys_exit = 1)
    xor  ebx, ebx              ; exit code
    int  0x80

除了通過在EDX中設置顯式長度來修復此錯誤外,我還重新排列了您的代碼以減少分支數量。 這應該使它更有效,但更重要的是,它使它更具可讀性。 另請注意,我已將cmp reg, 0更改為test reg, reg ,這幾乎總是首選形式 類似地, 使用xor reg, reg over mov reg, 0將寄存器歸零

在線嘗試!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM