[英]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.