section .data
msg1 db 'Introduce lenght !',0xA,0xD
len1 equ $-msg1
nl db 0xA,0xD
pal db 'Is palindrome',0xA,0xD
lenpal equ $-pal
nonpal db 'Is not palindrome ',0xA,0xD
lennonpal equ $-nonpal
poz db 0
section .bss
index1 resb 1
index2 resb 1
lenght resb 1
array times 10 resb 1
sep resb 1
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,msg1
mov edx,len1
int 0x80
mov eax,3
mov ebx,0
mov ecx,lenght
mov edx,1
int 0x80
mov cl,[lenght]
sub cl,'0'
mov [lenght],cl
mov [index2], byte 0
mov al,[index2]
add al,[lenght]
mov [index2],al
mov eax,3
mov ebx,0
mov ecx,sep
mov edx,1
int 0x80
read:
mov al,[poz]
inc al
mov [poz],al
mov eax,3
mov ebx,0
mov ecx,array
add ecx,[poz]
mov edx,1
int 0x80
mov cl,[lenght]
dec cl
mov [lenght],cl
cmp byte [lenght],0
jne read
print_array:
mov eax,4
mov ebx,1
mov ecx,array
mov edx,[lenght]
int 0x80
mov [index1], byte 0
mov bl,[index1]
inc bl
mov [index1],bl
verify_pal:
; mov eax, array
mov esi ,array
mov ebx,[index1]
add esi,ebx
mov bl,[esi]
mov edi ,array
mov ebx,[index2]
add edi,ebx
mov cl,[edi]
cmp bl,cl
jne not_a_pal
mov bh,[index1]
inc bh
mov [index1],bh
mov ch,[index2]
dec ch
mov [index2],ch
mov al,[index1]
cmp al,[index2]
jng verify_pal
is_pal:
mov eax,4
mov ebx,1
mov ecx,pal
mov edx,lenpal
int 0x80
jmp exit
not_a_pal:
mov eax,4
mov ebx,1
mov ecx,nonpal
mov edx,lennonpal
int 0x80
jmp exit
exit:
mov eax,1
mov ebx,0
int 0x80
有人可以告诉我我的程序出了什么问题吗?我是一个完全的初学者,我试图弄清楚汇编是如何工作的,但这段代码总是以段错误结束。
jmp exit exit:
跳转到正下方的标签是多余的操作。执行可能会失败。
mov bl,[esi] mov edi ,array mov ebx,[index2]
在回文检查器中,您将第一个字节加载到 BL 寄存器中,但在销毁 BL 后立即将 index2 变量加载到 EBX 寄存器中。请记住,BL 不是一个独立的寄存器,而是 32 位寄存器 EBX 的最低 8 位的名称。
发生分段错误是因为您使用 resb
指令将 poz、lenght、index1 和 index2 变量定义为
byte。通常这可能没问题,但稍后在程序中您将在双字大小的操作中使用这些字节大小的变量!由于您的汇编器 (NASM) 不会为您检查大小,因此它会很乐意从字节大小的变量中读取双字(只需添加内存中恰好跟随的 3 个字节)。在这种情况下,像 FASM 这样与 NASM 非常接近的汇编器会警告您。
mov ecx,array add ecx,[poz]
mov ecx,array mov edx,[lenght]
mov esi ,array mov ebx,[index1] add esi,ebx mov bl,[esi]
mov edi ,array mov ebx,[index2] add edi,ebx mov cl,[edi]
对于其中一些,您可以通过简单地将变量的字节零扩展到寄存器的双字来摆脱它:
movzx edx, byte [length]
movzx ebx, byte [index1]
movzx ebx, byte [index2]
但是因为您正在编写32位代码,所以更好的解决方案是将(许多/大部分)变量定义为双字。
section .data
poz dd 0
...
section .bss
index1 resd 1
index2 resd 1
length resb 1
array times 10 resb 1
sep resb 1
冗余会使你的程序变得臃肿。index1 变量中:
mov [index1], byte 0
mov bl,[index1]
inc bl
mov [index1],bl
接下来是所有这些冗余代码片段的列表,我添加了正确的替换指令,以适合新的数据声明(三个双字变量):
mov cl,[lenght] sub byte [length], '0'
sub cl,'0'
mov [lenght],cl
mov [index2], byte 0 movzx eax, byte [length]
mov al,[index2] mov [index2], eax
add al,[lenght]
mov [index2],al
mov al,[poz] inc dword [poz]
inc al
mov [poz],al
mov cl,[lenght] dec byte [length]
dec cl jnz read
mov [lenght],cl
cmp byte [lenght],0
jne read
mov [index1], byte 0 mov dword [index1], 1
mov bl,[index1]
inc bl
mov [index1],bl
mov esi ,array mov esi, [index1]
mov ebx,[index1] mov bl, [array + esi]
add esi,ebx
mov bl,[esi]
mov edi ,array mov edi, [index2]
mov ebx,[index2] mov cl, [array + edi]
add edi,ebx
mov cl,[edi]
mov bh,[index1] inc esi
inc bh mov [index1], esi
mov [index1],bh
mov ch,[index2] dec edi
dec ch mov [index2], edi
mov [index2],ch
mov al,[index1] cmp esi, edi
cmp al,[index2] jb verify_pal
jng verify_pal
Nice and clean does it.
-
> mov eax,3
> mov ebx,0
> mov ecx,sep
> mov edx,1
> int 0x80
I suppose that *sep* stands for 'separator', but I don't see any use of this in the rest of your program. For clarity, it is always best to not keep such fragments lying around.