I'm looking to call malloc() from an ASM file.
In ASM:
extern malloc
didn't work. I would like to link the CStdLib.
What exactly does "didn't work" mean? You need to do more than just use extern, you need to link against the C Library. The easiest way is to use gcc to link. As you didn't mention if your code is 32 bit or 64, I will go with 32 bit. The process is basically the same for 64 bit.
extern exit, printf, malloc, free
global main
BUFFER_SIZE equ 27
section .data
fmtstr db "%s", 10, 0
section .text
main:
push BUFFER_SIZE
call malloc
add esp, 4 * 1
mov esi, eax
xor ecx, ecx
mov edx, 97
.FillBuffer:
mov byte [esi + ecx], dl
inc edx
inc ecx
cmp ecx, BUFFER_SIZE - 1
jne .FillBuffer
mov byte [esi + ecx], 0
push esi
push fmtstr
call printf
add esp, 4 * 2
push esi
call free
add esp, 4 * 1
push 0
call exit
add esp, 4 * 1
and the makefile:
APP=malloctest
all: $(APP) clean
$(APP): $(APP).o
gcc -o $(APP) $(APP).o
$(APP).o: $(APP).asm
nasm -f elf $(APP).asm
clean:
rm $(APP).o
Related
This question already has answers here:
what is the difference between byte and dword in assembly and how to use them [duplicate]
(1 answer)
How to load a single byte from address in assembly
(1 answer)
Closed 3 months ago.
I am trying to implement a function in x86 nasm assembler which removes every n-th character from string. However, I am experiencing quite unexpected behaviour and don't really understand why it doesn't work.
// main.c
#include <stdio.h>
char *rem(char *s, int n);
int main(int argc, char *argv[])
{
char s[] = "abcabcabc";
int n = 3;
printf("%s\n", rem(s, n));
}
; rem.s
section .text
global rem
rem:
push ebp
mov ebp, esp
push esi
push edi
push ebx
mov eax, [ebp+8] ; read pointer
mov ecx, [ebp+8] ; write pointer
mov edx, [ebp+12] ; n
mov esi, 1 ; counter
loop:
cmp BYTE [eax], 0
jz fin
cmp edx, esi
jz remove
dont_remove:
; move current character to position
; pointed by the write pointer
mov edi, [eax]
mov [ecx], edi
inc ecx ; increase write pointer
inc eax ; increase read pointer
inc esi ; counter++
jmp loop
remove:
mov esi, 1 ; reset the counter
inc eax ; increase only read pointer
jmp loop
fin:
mov edi, [eax]
mov [ecx], edi
mov eax, [ebp+8]
pop ebx
pop edi
pop esi
pop ebp
ret
# Makefile
EXEFILE = main
OBJECTS = main.o rem.o
CCFMT = -m32
NASMFMT = -f elf32
CCOPT = -m32 -c
NASMOPT = -w+all
.c.o:
cc -g $(CCFMT) $(CCOPT) $<
.s.o:
nasm $(NASMFMT) $(NASMOPT) $<
$(EXEFILE): $(OBJECTS)
cc $(CCFMT) -o $(EXEFILE) $(OBJECTS)
clean:
rm *.o $(EXEFILE)
After running the code with command make && ./main I expected to see ababab (so that it removes all of the c's from "abcabcabc", in other way, removes every 3rd character). However it returns abacb. What is causing this issue? Thanks in advance for help
C code
#include <stdio.h>
int fibonacci(int);
int main()
{
int x = fibonacci(3);
printf("Fibonacci is : %d",x);
return 0;
}
Assembly
section .text
global fibonacci
fibonacci:
push ebp;
mov ebp, esp;
; initialize
mov dword [prev], 0x00000000;
mov dword [cur], 0x00000001;
mov byte [it], 0x01;
mov eax, dword [ebp + 8]; // n = 3
mov byte [n], al;
getfib:
xor edx,edx;
mov dl, byte [n];
cmp byte [it] , dl;
jg loopend;
mov eax,dword [prev];
add eax, dword [cur];
mov ebx, dword [cur];
mov dword [prev], ebx;
mov dword [cur] , eax;
inc byte [it];
jmp getfib;
loopend:
mov eax, dword [cur];
pop ebp;
ret;
section .bss
it resb 1
prev resd 1
cur resd 1
n resb 1
I was trying to run this assembly function in C code and on debugging , i saw that value in variable x in C code is right but there is some error coming when i use the printf function
Need Help on it
Command to compile:
nasm -f elf32 asmcode.asm -o a.o
gcc -ggdb -no-pie -m32 a.o ccode.c -o a.out
Click Below Pictures if they seem blurred
Below is debug before printf execute
Below is after printf execute
Your code does not preserve the ebx register which is a callee-preserved register. The main function apparently tries to do some rip-relative addressing to obtain the address of the format string for printf using ebx as a base register. This fails because your code overwrote ebx.
To fix this issue, make sure to save all callee-saved registers before you use them and then restore their value on return. For example, you can do
fibonacci:
push ebp
mov ebp, esp
push ebx ; <---
...
pop ebx ; <---
pop ebp
ret
My question: Why is it printing twice when I'm making one call to printf?
Note that yes, I'm aware I'm allocating space in heap for a variable stored on the stack. I'm only doing this to get used to malloc, pointers, and 'arrays' in NASM.
Compiling in x64 bit machine with:
nasm -f elf32 -o TEMP.o file.asm
and:
gcc -m32 -o exec TEMP.o
extern exit, printf, malloc, free
global main
section .data
format db "%s", 10
msg: db "Hello!!",10
BUF equ $-msg + 1
section .text
main:
push BUF ; How many bytes do we want to allocate
call malloc ; ptr stored in EAX
add esp, 4 ; clear the last thing on the stack (BUF)
mov esi, eax ; new source index at malloc pointer
xor ecx, ecx ; clear ECX (counter for us)
loop:
mov dl, [msg+ecx] ; mov letter into dl
mov BYTE [esi+ecx], dl ; cat dl onto array
inc ecx ; add 1 to our ounter
cmp ecx, BUF-1d
jl loop
xor edx, edx
mov BYTE [esi+ecx], dl
add esp, 4
mov esi, eax
push esi ;
push format
call printf
add esp, 4*2
push esi
call free
push 0
call exit
add esp, 4
You only need to end your strings with 0
format db "%s", 10, 0
msg: db "Hello!!",10 ,0
Okay i'v read the comments just now and see you said you had code that is meant to insert the 0s, i'd check that, because i copied/pasted your code and only added the 0s on the ends of the strings to make it output one string, i didn't even notice the insertion code let alone touch it, but i can only assume that is where your problem is.
I'm learning NASM at the moment and am making a simple program that does multiplication of any user-input variables through shifting and addition.
I've been running into a series of issues: My multiplicand is, for some reason, being given at the maximum data value a word can hold. Furthermore, my answer, if the program should get that far, is almost always wrong (even though I believe my algorithm is correct!).
extern printf
extern scanf
section .data
message: db "Enter your multiplicand: "
message_L: equ $-message
message2: db "The number you entered is: %d ", 10, 0
message2_L: equ $-message2
message3: db "Enter your multiplier: "
message3_L: equ $-message3
message4: db "Your multiplier is: %d ", 10, 0
message4_L: equ $-message4
message5: db "The product of this multiplication is: %d ", 10, 0
mesasge5_L: equ $-message5
fmt1: db "%d", 0
section .bss
multiplicand: resw 1
multiplier: resw 1
product: resw 1
section .text
global main
scanInt:
push ebp
mov ebp, esp
sub esp, 2
lea eax, [ebp-2]
push eax
push dword fmt1
call scanf
mov ax, word[ebp-2]
mov esp, ebp
pop ebp
ret
main:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, message_L
int 80h
call scanInt
mov word[multiplicand], ax
mov word[product], ax
jmp print1
main2:
mov eax, 4
mov ebx, 1
mov ecx, message3
mov edx, message3_L
int 80h
call scanInt
mov word[multiplier], ax
jmp print2
main3:
mov ax, word[multiplicand]
jmp check
check:
cmp word[multiplier], 2
jz printAnswer
ror [multiplier], 1
shl word[multiplier], 1
jc carry
shr word[multiplier], 1
shr word[multiplier], 1
shl word[product], 1
jmp check
carry:
add word[product], ax
shr word[multiplier], 1
clc
jmp check
endLoop:
mov eax, 1
mov ebx, 0
int 80h
printAnswer:
push ebp
mov ebp, esp
push word[product]
push dword message5
call printf
add esp, 12
mov esp, ebp
pop ebp
jmp endLoop
print1:
push ebp
mov ebp, esp
push dword[multiplicand]
push dword message2
call printf
add esp, 12
mov esp, ebp
pop ebp
jmp main2
print2:
push ebp
mov ebp, esp
push dword[multiplier]
push dword message4
call printf
add esp, 12
mov esp, ebp
pop ebp
jmp main3
I think your main problem comes from using word variables. Making a two-byte buffer on the stack, and calling scanf to read into it is almost certainly a problem. Pushing a word in 32-bit code is "legal", but likely to cause problems. In one instance, you call printf with two variables, and add esp, 12 afterwards. Make 'em all dwords and keep your stack manipulation in four-byte chunks. I think that'll cure most of your problems.
The man pages explicitly suggest not mixing high-level, buffered I/O, functions with low level functions (printf, scanf, fopen(), fread(), fwrite(), etc. are high level functions, open(), read(), write()... and system calls are low level functions). I don't think that this is causing any of your problems, but it can cause weird results. For example, printf doesn't print anything until the buffer is flushed. Ending with a linefeed, or using another high level I/O function will flush the buffer. sys_read, for example, does not. I'd stick to one or the other.
Good luck!
I need to get my char pointer and after that i print it on the screen to see if it works ok.
I read the text from a file and put in my char pointer (sizeof(char*) + filesize) + 1.. in the end i put the '\0'.
If i printf my char* its fine
Here is my asm code
; void processdata(char* filecontent);
section .text
global processdata
extern printf
section .data
FORMAT: db '%c', 10, 0 ; to break the line 10, 0
processdata:
push ebp
mov ebp, esp
mov ebx, [ebp]
push ebx
push FORMAT
call printf
add esp, 8
when i run it i just see trash in my variable.
As violet said:
; void processdata(char* filecontent);
section .text
[GLOBAL processdata] ;global processdata
extern printf
section .data
FORMAT: db '%c', 0
EQUAL: db "is equal", 10, 0
processdata:
lea esi, [esp]
mov ebx, FORMAT
oook:
mov eax, [esi]
push eax
push ebx
call printf
inc esi
cmp esi, 0x0
jnz oook
Thanks
quote demonofnight
But if i need to increment, can i do that?
Using your original function arg of char* and your %c format, something like this:
lea esi, [esp+4]
mov ebx, FORMAT
oook:
mov eax, [esi]
push eax
push ebx
call printf
inc esi
cmp [esi], 0x0
jnz oook
[edit: ok sry, i hacked that quickly into some shenzi winOS inline __asm block]
here's a complete thing done in linux and nasm:
; ----------------------------------------------------------------------------
; blah.asm
; ----------------------------------------------------------------------------
extern printf
SECTION .data ;local variables
fmt: db "next char:%c", 10, 0 ;printf format, "\n",'0'
SECTION .text ;hack in some codes XD
global foo
foo: ;foo entry
push ebp ;set up stack frame
mov ebp,esp
mov esi, [ebp+8] ;load the input char array to the source index
oook: ;loop while we have some chars
push dword [esi] ;push next char addy in string to stack
push dword fmt ;push stored format string to stack
call printf
add esp, 8 ;restore stack pointer
inc esi ;iterate to next char
cmp byte [esi], 0 ;test for null terminator byte
jnz oook
mov esp, ebp ;restore stack frame
pop ebp
mov eax,0 ;return 0
ret ;done
blah.c (that invokes the .asm foo) :
/*-----------------------------------------------
blah.c
invokes some asm foo
------------------------------------------------*/
#include <stdio.h>
void foo(char*);
int main() {
char sz[]={"oook\n"};
foo(sz);
return 0;
}
&here's the commandline stuff:
$ nasm -f elf blah.asm -o blah.o
$ gcc -o blah blah.c blah.o
$ ./blah
next char:o
next char:o
next char:o
next char:k
next char:
$
$ nasm -v
NASM version 2.09.08 compiled on Apr 30 2011
$ uname -a
Linux violet-313 3.0.0-17-generic #30-Ubuntu SMP Thu Mar 8 17:34:21 UTC 2012 i686 i686 i386 GNU/Linux
Hope it works for you ;)
On linux x86 the first function parameter is in ecx. The printf format for printing a pointer is "%p".
So something along
...
FORMAT: db '%p', 10, 0 ; to break the line 10, 0
processdata:
mov eax, [esp+4]
push eax
push format
call printf
add esp, 8
ret
should work, assuming the rest of your code is correct and your are using gcc's calling convention.
This is assuming that the pointer you want to print is on the stack.
The reason for the crash is probably that you push 12 bytes on the stack, but correct the stack pointer by only 8.