变量在我的汇编代码中意外更改
the variable changed unexpected in my assembly code
我的系统是ubuntun 16.04 32bits nasm
我写了一个代码,它接受输入“str_a str_b”,它会给你 str_a 的长度和 str_b 的长度。
但是如果我输入“1 1”,str_a的长度应该是1,但是当我输出它时,它是3.If我输入“11 11”,输出就变成了5,这几乎让我发疯。
当 str_a 的长度为“1 1”时,我尝试打印一个“a”,它只打印了一次。
这里是核心代码
begin_input_and_stroge:
;input
pusha
mov eax, 3
mov ebx, 2
mov ecx, input
mov edx, 50
int 80h
mov byte[len_a],0
mov byte[len_b],0
mov edx,0
mov ecx,0
set_num_a:
cmp byte[input+edx]," " ;if meet " ",it will start calculate length of b
je set_num_b_ini
inc byte[len_a]
inc edx
inc ecx
jmp set_num_a
set_num_b_ini:
mov ecx,0
set_num_b:
cmp byte[input+edx],0
je finish_input_and_stroge
inc byte[len_b]
inc edx
inc ecx
jmp set_num_b
finish_input_and_stroge:
dec byte[len_b]
popa
ret
而且是整个文件,因为我试着做了别的东西,所以看起来很丑
section .data ;Data segment
rev_a TIMES 23 db 0
rev_b TIMES 23 db 0
text db "split"
space db " "
string db '===========', 0Ah
length equ 13
;rev_a the reverse array of a ,[3,2,1]
;num_a the string of a [1,2,3]
;len_a the length of num_a
section .bss ;Uninitialized data
copy_text resb 50
input resb 50
len_a resb 0
len_b resb 0
num_a resb 23
num_b resb 23
flag resb 0
output_len resb 10
print_test resb 10
section .text ;Code Segment
global _start
_start:
call begin_input_and_stroge
mov ecx,0
mov al,byte[len_a]
add al,"0"
mov byte[print_test+ecx],al
call output
mov al,"0"
mov byte[print_test+ecx],al
call output
; mov al,"0"
; mov byte[print_test],al
; call output
; mov al,byte[len_b]
; add al,"0"
; mov byte[print_test],al
; call output
; mov edx,0
; mov ecx,0
; mov ecx,dword[len_a]
; dec ecx
; output_num_a:
; cmp ecx,0
; je finish_output_num_a
; mov al,byte[num_a+ecx]
; mov byte[print_test+edx],al
; inc edx
; dec ecx
; jmp output_num_a
; finish_output_num_a:
; call output
; Exit code
mov eax, 1
mov ebx, 0
int 80h
output:
pusha
mov eax, 4
mov ebx, 1
mov ecx, print_test
mov edx, 10
int 80h
popa
ret
begin_input_and_stroge:;输入 ,并将其存储进字符串,同时记录相应的长度
;input
pusha
mov eax, 3
mov ebx, 2
mov ecx, input
mov edx, 50
int 80h
mov byte[len_a],0
mov byte[len_b],0
mov edx,0
mov ecx,0
set_num_a:
cmp byte[input+edx]," ";若是空格,开始给num_b设置值
je set_num_b_ini
; mov al,byte[input+edx]
; sub al,"0"
; mov byte[num_a+ecx],al
inc byte[len_a]
; mov al,"a"
; mov byte[print_test],al
; call output
inc edx
inc ecx
jmp set_num_a
set_num_b_ini:
mov ecx,0
set_num_b:
cmp byte[input+edx],0
je finish_input_and_stroge
; mov al,byte[input+edx]
; sub al,"0"
; mov byte[num_b+ecx],al
inc byte[len_b]
inc edx
inc ecx
jmp set_num_b
finish_input_and_stroge:
dec byte[len_b];len_b减去1
popa
ret
len_a resb 0
len_b resb 0
num_a resb 23
因为resb 0
根本没有保留任何字节,所以这3个标签实际上指向同一个内存字节。代码相当于:
len_a:
len_b:
num_a resb 23
因此,您应用于 len_a 和 len_b 的增量将相加。这就是为什么你会得到意想不到的结果。你需要的是 len_a resb 1
len_b resb 1
.
dec byte[len_b]
popa
ret
这是针对 begin_input_and_stroge[=50 的另一个问题对 len_b 变量进行的丑陋且可能是最后一刻的更正=] 常规。当 set_num_a 循环找到一个 space 字符并且你转换到 set_num_b 循环时,你真的应该跳过那个字符 (inc edx
) 而不是将它与最后的零字节进行比较。因为那个 " " <> 0,所以 cmp
肯定会落入不需要的 inc byte [len_b]
。
我在下面的代码中删除了 ECX
上多余的操作:
...
xor edx, edx
mov [len_b], dl
set_num_a:
cmp byte [input+edx], " "
je set_num_b_ini
inc edx
jmp set_num_a
set_num_b_ini:
mov [len_a], dl
inc edx ; Skip the " "
set_num_b:
cmp byte [input+edx], 0
je finish_input_and_stroge
inc byte [len_b]
inc edx
jmp set_num_b
finish_input_and_stroge:
popa
ret
在注释掉的部分中,有一行内容为:
; mov ecx,dword[len_a]
请格外小心您使用的尺码。如果将 len_a 变量定义为 byte,则需要在整个程序中始终如一地使用它。如果您需要从该字节大小的变量加载 dword 寄存器 ECX
,您可以使用 MOVZX
:
movzx ecx, byte [len_a]
我的系统是ubuntun 16.04 32bits nasm
我写了一个代码,它接受输入“str_a str_b”,它会给你 str_a 的长度和 str_b 的长度。
但是如果我输入“1 1”,str_a的长度应该是1,但是当我输出它时,它是3.If我输入“11 11”,输出就变成了5,这几乎让我发疯。 当 str_a 的长度为“1 1”时,我尝试打印一个“a”,它只打印了一次。
这里是核心代码
begin_input_and_stroge:
;input
pusha
mov eax, 3
mov ebx, 2
mov ecx, input
mov edx, 50
int 80h
mov byte[len_a],0
mov byte[len_b],0
mov edx,0
mov ecx,0
set_num_a:
cmp byte[input+edx]," " ;if meet " ",it will start calculate length of b
je set_num_b_ini
inc byte[len_a]
inc edx
inc ecx
jmp set_num_a
set_num_b_ini:
mov ecx,0
set_num_b:
cmp byte[input+edx],0
je finish_input_and_stroge
inc byte[len_b]
inc edx
inc ecx
jmp set_num_b
finish_input_and_stroge:
dec byte[len_b]
popa
ret
而且是整个文件,因为我试着做了别的东西,所以看起来很丑
section .data ;Data segment
rev_a TIMES 23 db 0
rev_b TIMES 23 db 0
text db "split"
space db " "
string db '===========', 0Ah
length equ 13
;rev_a the reverse array of a ,[3,2,1]
;num_a the string of a [1,2,3]
;len_a the length of num_a
section .bss ;Uninitialized data
copy_text resb 50
input resb 50
len_a resb 0
len_b resb 0
num_a resb 23
num_b resb 23
flag resb 0
output_len resb 10
print_test resb 10
section .text ;Code Segment
global _start
_start:
call begin_input_and_stroge
mov ecx,0
mov al,byte[len_a]
add al,"0"
mov byte[print_test+ecx],al
call output
mov al,"0"
mov byte[print_test+ecx],al
call output
; mov al,"0"
; mov byte[print_test],al
; call output
; mov al,byte[len_b]
; add al,"0"
; mov byte[print_test],al
; call output
; mov edx,0
; mov ecx,0
; mov ecx,dword[len_a]
; dec ecx
; output_num_a:
; cmp ecx,0
; je finish_output_num_a
; mov al,byte[num_a+ecx]
; mov byte[print_test+edx],al
; inc edx
; dec ecx
; jmp output_num_a
; finish_output_num_a:
; call output
; Exit code
mov eax, 1
mov ebx, 0
int 80h
output:
pusha
mov eax, 4
mov ebx, 1
mov ecx, print_test
mov edx, 10
int 80h
popa
ret
begin_input_and_stroge:;输入 ,并将其存储进字符串,同时记录相应的长度
;input
pusha
mov eax, 3
mov ebx, 2
mov ecx, input
mov edx, 50
int 80h
mov byte[len_a],0
mov byte[len_b],0
mov edx,0
mov ecx,0
set_num_a:
cmp byte[input+edx]," ";若是空格,开始给num_b设置值
je set_num_b_ini
; mov al,byte[input+edx]
; sub al,"0"
; mov byte[num_a+ecx],al
inc byte[len_a]
; mov al,"a"
; mov byte[print_test],al
; call output
inc edx
inc ecx
jmp set_num_a
set_num_b_ini:
mov ecx,0
set_num_b:
cmp byte[input+edx],0
je finish_input_and_stroge
; mov al,byte[input+edx]
; sub al,"0"
; mov byte[num_b+ecx],al
inc byte[len_b]
inc edx
inc ecx
jmp set_num_b
finish_input_and_stroge:
dec byte[len_b];len_b减去1
popa
ret
len_a resb 0 len_b resb 0 num_a resb 23
因为resb 0
根本没有保留任何字节,所以这3个标签实际上指向同一个内存字节。代码相当于:
len_a:
len_b:
num_a resb 23
因此,您应用于 len_a 和 len_b 的增量将相加。这就是为什么你会得到意想不到的结果。你需要的是 len_a resb 1
len_b resb 1
.
dec byte[len_b] popa ret
这是针对 begin_input_and_stroge[=50 的另一个问题对 len_b 变量进行的丑陋且可能是最后一刻的更正=] 常规。当 set_num_a 循环找到一个 space 字符并且你转换到 set_num_b 循环时,你真的应该跳过那个字符 (inc edx
) 而不是将它与最后的零字节进行比较。因为那个 " " <> 0,所以 cmp
肯定会落入不需要的 inc byte [len_b]
。
我在下面的代码中删除了 ECX
上多余的操作:
...
xor edx, edx
mov [len_b], dl
set_num_a:
cmp byte [input+edx], " "
je set_num_b_ini
inc edx
jmp set_num_a
set_num_b_ini:
mov [len_a], dl
inc edx ; Skip the " "
set_num_b:
cmp byte [input+edx], 0
je finish_input_and_stroge
inc byte [len_b]
inc edx
jmp set_num_b
finish_input_and_stroge:
popa
ret
在注释掉的部分中,有一行内容为:
; mov ecx,dword[len_a]
请格外小心您使用的尺码。如果将 len_a 变量定义为 byte,则需要在整个程序中始终如一地使用它。如果您需要从该字节大小的变量加载 dword 寄存器 ECX
,您可以使用 MOVZX
:
movzx ecx, byte [len_a]