Using the return value of strstr() in NASM? - c

I am trying to use the strstr C function in a NASM assembly program but cannot seem to get it to print out correctly. I have tried multiple variations of this, but I think I may be misinterpreting how NASM returns the pointer value from C as I either get a blank line returned in the printf or a '(null)'. Could some help fill me in as why I cannot get the correct return value to be printed?
section .data
str1 db "Here is some text with a word",0x0A,0x00
str2 db "text",0x0A, 0x00
strFmt db "%s",0x0A,0x00
global _start
extern printf
extern strstr
section .text
_start:
push ebp
mov ebp, esi
push str2
push str1
call strstr
add esp, 8
mov dword [myString], eax
push dword [myString]
push strFmt
call printf
add esp, 8
_exit:
mov ebx, 0
mov eax, 1
int 0x80

The main issue is the 0x0A in the search string. It's a part of the string, as everything before the terminating null is a part of it. It must be listed separately because C-style escape sequences inside strings won't be resolved by the assembler. A "test\n" won't be found by strstr. Remove the 0x0A and strstr will found the search string.
As Cody Gray mentioned, the block with mov ebp, esi is strange—you probably meant the idiomatic mov ebp, esp. Moreover, it's not needed in this example. Also superfluous is the indirection with myString—just push eax directly.
printf writes the output first to a buffer. You exit the program with a int 80h system call. This call will destroy everything of the process including the printf-buffer. So the buffer won't be outputted. There are two ways to solve the problem:
1) Use the C function exit instead of the system call:
section .data
str1 db "Here is some text with a word",0x0A,0x00
str2 db "text",0x00
strFmt db "%s",0x0A,0x00
global _start
extern printf, strstr, exit
section .text
_start:
push str2
push str1
call strstr
add esp, 8
push eax
push strFmt
call printf
add esp, 8
_exit:
push 0
call exit
2) Add a call to the C function fflush:
section .data
str1 db "Here is some text with a word",0x0A,0x00
str2 db "text",0x00
strFmt db "%s",0x0A,0x00
global _start
extern printf, strstr, fflush
section .text
_start:
push str2
push str1
call strstr
add esp, 8
push eax
push strFmt
call printf
add esp, 8
push 0
call fflush
_exit:
mov ebx, 0
mov eax, 1
int 0x80

Related

How can I change the value of a single byte using NASM?

Using NASM, I need to change a character in a string at a given index and print the string in its new form. Here is a simplified version of my code:
;test_code.asm
global main
extern printf
output_str: db "----------"
index: dq 7
main:
push rbp
mov rdi, output_str
mov rax, index
mov byte[rdi + rax], 'x'
xor rax, rax
call printf
pop rbp
ret
I then compile using:
nasm -felf64 test_code.asm && gcc test_code.o -lm
and get a seg fault. Would someone please point out the flaw here? I can't seem to find it myself.
your string is in the .text section of the executable, which is read only by default. Either you allocate a buffer on the stack, copy the string and you modify it there, or you put the string in the .data section (which is read/write) using the section directive. In this last case, notice that the character replacement will be persistent, i.e. even later in the program the string will remain modified;
if you want to print that string with printf it has to be NUL-terminated. Add a ,0 to the end of the db line;
that mov rax, index is wrong - index is the address of the qword you wrote above, while you actually want to copy in rax the datum wrote there; you probably want mov rax, [index].
So, something like
;test_code.asm
global main
extern printf
section .data
output_str:
db "----------",0
section .text
index:
dq 7
main:
push rbp
mov rdi, output_str
mov rax, [index]
mov byte[rdi + rax], 'x'
xor rax, rax
call printf
pop rbp
ret

Assembly Language modify input string;

I am trying to write an assembly program that take in a string from the file text.txt. Then the program encoded the string in ROT13 and using printf to display the result. However, It seem like i failed to read the file and get put in an infinite loop in "nextChar:" . I'm sure I miss something but not sure what it is.
Thank you
;%include "glibc"
section .data ;section declaration
getFmt: dd "%c",10,0
fileFmt: dd "%s",10,0
countFmt: dd "%d",10,0
output: dd "output.txt",10,0
writeCode: dd "w",10,0
readCode: dd "r",10,0
EOF: db -1 ;I read that this may need to be 0, instead of -1
Filename db "text.txt",0
section .bss
char:
buf: resb 1
section .text ;section declaration
global main
extern fopen
extern fclose
extern printf ;you can use this for debugging, otherwise not needed
extern getchar
extern putchar
extern scanf
main:
mov ebx, Filename ; push file name to ebx
push readCode ;set file to "read" mode
push ebx ;push file name
call fopen ;open file
add esp,8
cmp eax,0 ;see if file opened correctly
jne nextChar
ret
nextChar:
push ebx ; Push file handle on the stack
mov ebx,eax ; Save handle of opened file in ebx push ebx
push dword [char] ;get the next char from input file
push getFmt ;
call getchar ;use getchar function
add esp,12 ;clear the stack
cmp eax,0 ; A returned null indicates error or EOF
jle done ; If we get 0 in eax, close up & return
add dword [char],13 ;add 13 to the ASCII value
push dword [char] ; push to print
push getFmt ;
call printf ;use printf function
add esp, 8 ;clear the stack
jmp nextChar
done:
push ebx ; Push the handle of the file to be closed
call fclose ; Closes the file whose handle is on the stack
add esp,4 ; Clean up the stack
ret ; Go home
You have a loop that will be exited if getchar returns 0. If your file never has a zero byte in it this won't happen. Instead, getchar will continue to return EOF and your loop will go on indefinitely.
Check the value of EOF in your environment (usually -1, but always outside the range 0-255) and use that as the limiter for the loop.

Printing out Twice NASM

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.

Can we push local variable to stack in assembly

I made a simple program which will just push a number and display it on the screen but
don't know what is going wrong
section .data
value db 10
section .text
global main
extern printf
main:
push 10 //can we push value directly on stack?
call printf
add esp,4
ret
Getting Segmentation fault for above.
section .data
value db 10
section .text
global main
extern printf
main:
push [value]
call printf
add esp,4
ret
In second version will be pushing value pointed to by value variable on to stack
But getting "operation size not specified"
Yes, you can push any DWORD value (in 32-bit assembler) onto the stack.
The problem in the first code fragment is that printf expects the first argument to be a format string (in C, you'd write printf("%d\n", 10);). So something like
section .data
fmt db "%d", 10, 0
...
push 10
push fmt
call printf
add esp, 8
will work.
In the second code fragment, instead of push [value] you should write push dword [value], but that's not correct if your value variable is a single byte. Either declare it as a DWORD (dd), or perform
movsx eax, byte [value] ; if it's a signed integer; movzx for unsigned
push eax
And one more thing. When calling printf (or any of the C library functions), beware of stack alignment. Some platforms require that stack is 16-byte aligned at the time of a function call (this is necessary for correct execution of optimized CPU instructions like SSE). So, to make the stack aligned:
push ebp
mov ebp, esp
sub esp, 8 ; reserve 8 bytes for parameters
and esp, -16 ; align the stack (the reserved space can increase)
mov dword [esp], fmt ; put parameters into stack
mov dword [esp+4], 10
call printf
mov esp, ebp ; restore stack
pop ebp

x86 Assembly: Loops!

Okay, long story short, I'm learning assembly, and I'm trying to make a loop print out the ascii characters "0" - "9".
So, I did all of the basics I've been seeing in examples, like saving register states with pushad and popad, allocating stack space, and making sure I leave things the way they started.
So I managed this small example:
;
; Hello_World.asm
; (NASM Syntax, Windows)
extern _printf
section .text
_main:
pushad ; save register states
push ebp ; save old stack
mov ebp, esp ; prepare new stack
sub esp, 1*4 ; allocate 4 bytes
mov byte [esp + 0], 48 ; add ascii '0' to stack
mov byte [esp + 1], 0 ; add ascii NULL terminator to stack
push esp; ; push the string in the stacks refrence
call _printf ; call printf()
add esp, 4 ; pop string refrence
add esp, 1*4 ; deallocate 4 bytes
mov esp, ebp ; close this stack
pop ebp ; restore old stack
popad ; restore register states
ret ; leave this function
This works, it prints out '0', but that's a little on the safe side. I tried adding a loop into it, but things just fall apart there. I read that the 'loop' opcode is supposed to decrement the ECX register, and go back to the label parameter should ECX > 0, however, I don't think I've quite got it yet.
So I add a few lines, and come up with this:
;
; Hello_World.asm
;
extern _printf
global _main
section .text
_main:
pushad ; save register states
push ebp ; save old stack
mov ebp, esp ; prepare new stack
sub esp, 1*4 ; allocate 4 bytes
mov byte [esp + 0], 48 ; add ascii '0' to stack
mov byte [esp + 1], 0 ; add ascii NULL terminator to stack
mov ecx, 9 ; set loop counter to 9
aLoop:
inc byte [esp + 0] ; increment ascii character
push esp; ; push the string in the stacks refrence
call _printf ; call printf()
add esp, 4 ; pop string refrence
loop aLoop ; loop back to aLoop if ecx > 0
add esp, 1*4 ; deallocate 4 bytes
mov esp, ebp ; close this stack
pop ebp ; restore old stack
popad ; restore register states
ret ; leave this function
Well, now things go crazy. I run it in command prompt and I hear this beeping through my headphones, and it's cycling through every ascii character, printing them all out. So after about 5 seconds of flying characters, I assume something overflows, and it just crashes.
I'm pretty new to assembly (today's my first day of real coding), and I don't see what's going wrong. Could someone please explain how I could better implement a loop ?
Thanks ahead!
-Jason
Does the "_printf" subroutine preserve the contents of ECX? If not, that could be your problem. Try saving it across the call.
okay, well, what you're describing is that the loop isn't terminating for some reason. That means the problem pretty well has to be here:
add esp, 4 ; pop string refrence
loop aLoop ; loop back to aLoop if ecx > 0
This sounds like a job for a debugger: what's really happening to ecx?
Well, I note that you're setting ecx to 9. You're then adding 4 to esp. When are you changing ecx? (Yes, I know it's supposed to be happening in the loop instruction, but if that were working you wouldn't be asking. What's really happening to ecx?)
The beeping, by the way, is easy: as you cycle through all the ASCII characters, you're hitting ASCII 0x07, the BEL character.
aLoop:
inc byte [esp + 0] ; increment ascii character
push ecx; ; save ecx
push esp; ; push the string in the stacks refrence
call printf ; call printf()
add esp, 4 ; pop string refrence
pop ecx
loop aLoop ; loop back to aLoop if ecx > 0
The caller-saved registers are eax, ecx, edx. The called subroutine is allowed to modify these registers. Look for caller-saved vs callee-saved registers using a search engine. Should give you more details.

Resources