Assembly NASM x86 - Putting char into array - arrays

I need to make a program that open a file, read it character by character and save it into an array in Assembly NASM x86. Currently, the program is able to open a file using stdin and read the character by using getchar(). However, i am stuck on the saving the char into an array and need help on this part.
Thank you
; Run it this way:
; test < (input file)
; Build using these commands:
; nasm -f elf -g -F stabs test.asm
; gcc –m32 -o test.o test
;
SECTION .bss ; Section containing uninitialized data
TextLenght EQU 1024 ; Define length of a line of text data
Text resb TextLenght ; Define array
SECTION .data ; Section containing initialised data
fileFmt: db "%c",0
SECTION .text ; Section containing code
extern putchar
extern getchar
extern printf
global main; Linker needs this to find the entry point!
main :
start:
nop ; This no-op keeps gdb happy...
mov eax, 0
mov edx, 0
mov ecx, 0
mov ebx, 0
; Read a buffer full of text from stdin:
read:
call getchar ; call getchar to get input from stdin, char is save in eax
cmp al, -1
jle Done ; if return -1, we at EOF
cmp eax, 97 ; get rid of 'enter' char
jl read
;mov Text, eax; try to save char in eax into array, don;t work
push eax ;push eax to print
push fileFmt
call printf
add esp, 8 ; clear the stack
jmp read
Done:
mov eax,1 ; Code for Exit Syscall
mov ebx,0 ; Return a code of zero
int 80H ; Make sys_exit kernel call

Related

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.

Reading text file line by line NASM

I'm new in assembly programming and I have an assignment in which I have to read a text file line by line and use what is written in the file and pass it to another function. My problem is that I'm not sure of how to read the text this way because from what I have discovered for reading a text file first I have to create a buffer reserving certain quantity of bytes for storing what is in the file. Howerver in this case I want to read line by line (like a loop) until the end of file so I dont know how much bytes I have to reserve. Thanks.
Btw here is the code I'm trying to use:
SECTION .data
file_name db 'instruct.txt',0
SECTION .bss
fd_out resb 1
fd_in resb 1
info resb 20
SECTION .text
global main
main: ;tell linker entry point
push ebp
mov ebp, esp
push ebx
;open the file for reading
mov eax, 5
mov ebx, file_name
mov ecx, 2
mov edx, 0777 ;read, write and execute by all
int 0x80
mov [fd_in], eax
loop:
;read from file
mov eax, 3
mov ebx, [fd_in]
mov ecx, info
mov edx, 5
int 0x80
cmp eax, 0
;check EOF
je exit
; print the info
mov eax, 4
mov ebx, 1
mov ecx, info
mov edx, 5
int 0x80
;
jmp loop
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
exit:
; close the file
mov eax, 6
mov ebx, [fd_in]
pop ebx
mov esp, ebp
pop ebp
ret
use mmap syscall, read entire file to memory and search for 0x0A sequence. This is the ASCII code for end of line. Perhaps usefull too to check for 0x0D (in case you are dealing with windows text files. There the sequence 0x0A,0x0D indicates an new line and thus an end of line.
mmap will try to allocate memory for you without the overhead of administration for you. Otherwise determine the file length and reserve memory with syscall sbrk. Works also but you have to program a bit more. My suggestion is that mmap is the best way.

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.

Get char pointer in assembler function

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.

how to call C functions from assembly routines and link the C and assembly files using nasm and gcc

I want to call at least 1 C function from assembly. It is because I'm doing my own tiny OS from scratch(out of nothing). The reason i want to call c function from my boot loader. I can understand assembly but poor in writing my own program. So if i could transfer control from assembly procedure to c procedure my job is made easier.
So how to link assembly pgm and C program files into one. It is ok for me even if the file size exceeds 512 bytes.
I am doing this on Windows 7 with help of mingw. my c compiler is gcc and assembler is nasm.
easier to just show you an example, I found this on the internet a while ago and saved it as a source on my computer, not sure where from though
; printf1.asm print an integer from storage and from a register
; Assemble: nasm -f elf -l printf.lst printf1.asm
; Link: gcc -o printf1 printf1.o
; Run: printf1
; Output: a=5, eax=7
; Equivalent C code
; /* printf1.c print an int and an expression */
; #include
; int main()
; {
; int a=5;
; printf("a=%d, eax=%d\n", a, a+2);
; return 0;
; }
; Declare some external functions
;
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 5 ; int a=5;
fmt: db "a=%d, eax=%d", 10, 0 ; The printf format, "\n",'0'
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; set up stack frame
mov ebp,esp
mov eax, [a] ; put a from store into register
add eax, 2 ; a+2
push eax ; value of a+2
push dword [a] ; value of variable a
push dword fmt ; address of ctrl string
call printf ; Call C function
add esp, 12 ; pop stack 3 push times 4 bytes
mov esp, ebp ; takedown stack frame
pop ebp ; same as "leave" op
mov eax,0 ; normal, no error, return value
ret ; return

Resources