变量在我的汇编代码中意外更改

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_alen_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]