Использование пользовательских vars в сборке nasm x86 - PullRequest
0 голосов
/ 20 апреля 2019

Я пытаюсь создать связанный список (для создания несвязанного калькулятора) в сборке. Каждый узел имеет размер 5 байтов, 1 байт для данных и 4 байта для указания следующего узла.

Я получил значение, которое хочу вставить в поле данных, и не могу заставить метод append работать. Я продолжаю получать ошибку сегментации (дамп ядра).

Я пробовал pushad, ассигнование и popad, и все та же ошибка.

Кроме того, если я создаю переменную в разделе bss, почему я должен использовать [my_var] всякий раз, когда использую его.

Последний вопрос: почему в моем коде malloc меняет значение edx. edx должен быть счетчиком и после выделения он каким-то образом изменяется.

Пока я добавляю свой код.

;---- MY CODE ---
section .rodata         ; we define (global) read-only variables in .rodata section
        format_str: db "%s", 0  ; format string

    %macro  print_msg  1
        push %1                         ;String to write    
        push format_str                 ;string format for printing
        call printf                     ;calling c method "printf"
        add esp, 8
    %endmacro

    %macro  get_input 0
        push dword [stdin]              ;fgets File to read from
        push dword 80                   ;max input lenght
        push dword buffer               ;buffer to read to
        call fgets
        add esp, 12                     ;remove 3 pushed args from stack
    %endmacro

    %macro  allocate_node 0             ; allocates new node
        pushad
        push 5                  
        call malloc
        add esp, 8
        cmp eax, 0                      ;; if cannot allocate, prints err
        jl error_allocating
    %endmacro

    %macro  find_len 0                  ; finds input length
        mov ebx, buffer
        mov ecx, 0
        dec ebx
        %%count:
            inc ecx                 ;; index inc
            inc ebx                 ;; length ++
            cmp byte [ebx], 0xA     ;; check if buffer at ebx is '\n'
            jnz %%count
        dec ecx
    %endmacro

    %macro check_len_even 0             ; checks if input's length is odd or even.
        mov edx, 0
        mov eax, ecx
        mov ebx, 2
        div ebx                         ; Devide by 2 to check the carry
        cmp edx, 1
        jne do_nothing 
        mov ebx, [buffer]               ; if it is odd, add '0' at the start of the string.
        mov [buffer], byte '0'
        mov [buffer + 1], ebx
        do_nothing:
    %endmacro

    %define node_size 5 

section .text
    align 16
    global main 
    extern printf 
    extern fflush
    extern malloc 
    extern calloc 
    extern free 
    extern fgets  
    extern stdin

main: 
    push ebp
    mov ebp, esp
    jmp myCalc  

myCalc:
    print_msg user_msg
    get_input
    jmp parse_input

parse_input:                    
    cmp byte [buffer], 'q'
    je quit_program

    jmp create_list

create_list:                                ;; TODO : 2. check stack size - ERROR 

    find_len                                ; length is stored in ecx
    check_len_even

    mov edx, 0                              ;; iterates over the buffer
    string_to_hex:
    mov al, 0
    mov bl, 0
    mov eax, 0
        left:
            mov al, byte [buffer + edx]     ; al is buffer[edx]
            cmp al, 0xA                     ; if we are done reading the string ('\n')
            je finished
            cmp al, 0x39                    
            jg .handle_letter               
            .handle_num:                    ;if the curr letter is between 0-9
                sub al, 48                  ; Turn into number
                inc edx
                jmp right
            .handle_letter:                 ;if the curr letter is between A-F
                sub al, 55                  ; Turn into number
                inc edx
        right:
            mov bl,byte [buffer + edx]      ; bl is buffer[edx]
            cmp bl, 0x39                
            jg .handle_letter
            .handle_num:
                sub bl, 48
                jmp shift_reg
            .handle_letter:
                sub bl, 55

        shift_reg:                          ; Creating a number from two consecutive letter.
            shl al,4
            or al,bl
            jmp append                  

        append:                             ; allocating memory for new node and append it to the curr list. start of node is at eax.
            mov [curr_data], al
            allocate_node   
            mov ebx, [curr_data]
            mov [eax], byte ebx             ; moving value of the number to the data "filed" of curr node.
            cmp edx, dword 1                ; if its the first time, should point to null.
            je .set_null
            mov [eax + 1], dword tmp_ptr        ; if its not the first time, should point to the prev head of the list, stored in ebx.
            jmp .prepare_next_append

            .set_null:
                mov [eax + 1], dword 0x00   ; first time, point to null.

            .prepare_next_append:
                mov [tmp_ptr], dword eax                ; saving prev head
                inc edx                                 ; move to the next char in buffer
                jmp string_to_hex

    finished:
        jmp myCalc


quit_program:
    mov esp, ebp    
    pop ebp
    ret


error_allocating:
    print_msg malloc_err
    jmp myCalc


section .data
    user_msg: db  'calc: ',0
    overflow_err: db 'Error: Operand Stack Overflow', 10, 0
    insufficient_err: db 'Error: Insufficient Number of Arguments on Stack', 10, 0
    malloc_err: db 'Error: cannot allocate memory.', 10, 0

    op_counter: dd  0

section .bss
    curr_data: resb 1
    tmp_ptr: resb 1
    buffer: resb 80
    tmp_num: resb 1
    op_stack: resd 5                    ; Reserve 5 slots (uninitialized)
    op_stack_len: equ $ - op_stack      ; Size of op_stack
...