Я пытаюсь создать связанный список (для создания несвязанного калькулятора) в сборке. Каждый узел имеет размер 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