I'm trying to implement a linked list in assembly, so I have an 'array' (actually 20 bytes) to save the link for 5 possible lists. each 'link' is 5 bytes long (1 for data 4 for pointer - x86 machine). Now I called malloc and created 1 link and pushed a number into the first byte (decimal number) and moved the link pointer to the start of the array. after that I try to call malloc again to create a new link but the new link created overwrites the link I have allready pushed into the array and I have no idea why!!!. here is the code and some input/output examples:
section .rodata
LC0:
DB "The number is: %i", 10, 0 ; string
LC1:
DB "Memory allocation failed!!!", 10, 0 ; string
section .data
section .bss
numbers_stack:
RESB 20
link:
RESB link_size
section .text
align 16
global main
extern printf
extern malloc
extern gets
link_size EQU 5
_start:
jmp main
main:
%macro mymalloc 2 ;malloc macro
mov edx, %1 ; size to allocate
push edx
call malloc
add esp,4
test eax,eax
jz fail_exit
mov [%2], eax
%endmacro
%macro myprintf 1 ;printing macro
push %1
push LC0
call printf
add esp,8
%endmacro
mymalloc link_size,link
mov byte[link], 44
mov dword[numbers_stack],link
mov eax,0
mymalloc link_size,link ; allocate new link - *at this point the contents are allready overwritten
mov eax,[numbers_stack] ; get pointer to list head from numbers_array[0] into eax
mov edx,0
mov dl,byte[eax]
myprintf edx
output examples: it will always print out the number '40' where its supposed to print out '44' if i delete the second mymalloc it will print 44 as expected, please help! why is it still pointed to the old memory location when I obviously allocated a new one?!
You are basically missing one level of indirection. malloc
will return a pointer that you store in link
(thus it's size should be 4, not link_size
). Then, when you do mov byte[link], 44
you are overwriting this pointer and not writing into the allocated memory region. You need to load the pointer into a register (but of course malloc already returned it in eax
) and then dereference that, such as:
mov eax, [link]
mov byte [eax], 44
You will also need to adjust the pointer there and you don't need the numbers_stack
at all, lists just have a head
pointer. You might want to use the common established names such as head
, next
and node
so that others can more easily understand what you are talking about.
PS: if you are using libc functions you should use entry point main
and not _start
and link with all the necessary startup objects so that libc
has a chance to initialize properly. You should finally just ret
from main
, or use the exit
function but not the exit
syscall.
Update : here is a possible implementation that allocates 2 lists and prints the first value from each:
section .rodata
LC0:
DB "The number is: %i", 10, 0 ; string
LC1:
DB "Memory allocation failed!!!", 10, 0 ; string
section .bss
struc node
.next resd 1
.value resb 1
endstruc
list_heads:
RESD 5
section .text
global main
extern printf
extern malloc
extern gets
main:
%macro mymalloc 1 ;malloc macro
push %1 ; size to allocate
call malloc
add esp,4
test eax,eax
jz fail_exit
%endmacro
%macro myprintf 1 ;printing macro
push %1
push LC0
call printf
add esp,8
%endmacro
mymalloc node_size
mov [list_heads], eax
mov dword [eax + node.next], 0
mov byte [eax + node.value], 44
mymalloc node_size
mov [list_heads + 4], eax
mov dword [eax + node.next], 0
mov byte [eax + node.value], 11
mov eax, [list_heads] ; get pointer to first list head
movzx edx, byte [eax + node.value]
myprintf edx
mov eax, [list_heads + 4] ; get pointer to second list head
movzx edx, byte [eax + node.value]
myprintf edx
Hope this helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.