Home > Back-end >  the variable changed unexpected in my assembly code
the variable changed unexpected in my assembly code

Time:10-23

my system is ubuntun 16.04 32bits nasm

I wrote a code which take an input "str_a str_b",and it will give you the length of str_a and length of str_b.

However if I input"1 1",length of str_a supposed to be 1,but when I output it ,it was 3.If I input "11 11",the output just became 5,this almost drive me crazy. And I try to print an "a" when increase length of str_a when it is"1 1",it was just printed for one time.

here is the core code

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

and it is the whole file,because I tried to do something else,it look quite ugly

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

CodePudding user response:

len_a resb 0
len_b resb 0
num_a resb 23

Because resb 0 does not reserve any bytes at all, those 3 labels actually point to the same memory byte. The code is equivalent to:

len_a:
len_b:
num_a resb 23

Therefore the increments that you apply to len_a and len_b will add up. That's why you get the unexpected results. What you need is len_a resb 1 len_b resb 1.


dec byte[len_b]
popa
ret

This is an ugly and probably last minute correction on the len_b variable for another problem with the begin_input_and_stroge routine. When the set_num_a loop has found a space character and you transition to the set_num_b loop, you really should skip that character (inc edx) instead of comparing it to the final zero byte. Because that " " <> 0, the cmp is certain to fall through in an unwanted inc byte [len_b].

I the below code I removed the operations on ECX that were redundant:

    ...
    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

In the commented-out section you have a line that reads:

; mov ecx,dword[len_a]

Be extra careful with the sizes that you use. If you define the len_a variable as byte, you need to use it that way consistently throughout the program. If you need to load the dword register ECX from that byte-sized variable you can use MOVZX:

movzx ecx, byte [len_a]
  • Related