Using extrn prinf:near in MASM - masm

Hello have a MASM assembly question. In the code below:
What is- extrn printf:near
It is refering to prinf function being called externally but what does the :near signify?
; include C libraries
includelib msvcrtd
includelib oldnames
includelib legacy_stdio_definitions.lib ;for scanf, printf, ...
.data
prompt db "Enter a number: ", 0
fmt db "%i", 0
input sdword ?
output byte 'z' ; initialize to 'z' as default
.code
extrn printf:near
extrn scanf:near
public main
main proc
push offset prompt
call printf
add sp,4
; get input with scanf
push offset input
push offset fmt
call scanf
add sp, 8
cmp input, 0
je LOUTPUT
jg LPOS
jng LNEG
LPOS:
mov output, 'p'
jmp LOUTPUT
LNEG:
mov output, 'n'
jmp LOUTPUT
LOUTPUT:
push offset output
call printf
add sp, 4
ret
main endp
end

Related

Using the return value of strstr() in NASM?

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

Assembly NASM x86 - Putting char into array

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

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.

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.

Translate C code to Assembly

I need to translate this C code to assembly language code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int answer, i;
int right, wrong;
right = 0;
wrong = 0;
for(i =1; i < 11; i = i+1){
printf("What is %d + %d? ", i,i);
scanf( "%d", &answer);
if(answer == i + 1) {
printf("right! ");
right++;
}
else {
printf("Sorry, you're wrong. ");
printf("The answer is %d. ", i + 1);
wrong++;
}
}
printf("You got %d right and %d wrong. ", right, wrong );
return 0;
}
I really just need to know how to combine a variable with a string in assembly language like in the above C code. I think I can handle everything else. Could somebody tell me. Would I have to use some kind of reference[].
Note I'm using MASM and working out of Kip Irvine's Assembly Language for x86 processors 6th edition book
update heres the code I attempted to write over to MASM from one of the answerer's answer I keep getting a error. Like I said before I'm using Kip Irvine's Assembly Language so I have to include the library link INCLUDE Irvine32.inc
this is the error>>>> programb.obj : error LNK2019: unresolved external symbol _scanf referenced in function _main#0
INCLUDE Irvine32.inc
can somebody help me get this right
.data
string1 db "What is %d + %d? ", 0
string2 db "%d", 0
string3 db "right! ", 0
string4 db "Sorry, you're wrong. The answer is %d", 10, 0
string5 db "You got %d right and %d wrong.", 10, 0
answer dd 0
right dd 0
wrong dd 0
.code
main PROC
mov ebx, 1
L1:
cmp ebx, 11
je L2
push 1
push ebx
mov edx,OFFSET string1
call WriteString
add esp, 12
push answer
mov edx,OFFSET string2
call scanf
add esp, 8
inc ebx
cmp answer, ebx
jne L3
push ebx
mov edx,OFFSET string3
call WriteString
add esp, 8
inc right
jmp L1
L3:
push ebx
mov edx,OFFSET string4
call WriteString
add esp, 8
inc wrong
jmp L1
L2:
push wrong
push right
mov EDX,OFFSET string5
call WriteString
add esp, 12
exit
main ENDP
END main
programb.obj : error LNK2019: unresolved external symbol _scanf referenced in function _main#0
I'm sorry about the assembly language code....I don't know how to format it so it can be easier to read....
You can use the -S flag to gcc to produce the assembly code:
gcc myfile.c -S -o myfile.s
What I mean is that this assembly file should answer all your questions.
I was bored so I did this for you. I used NASM, rather than MASM. I assumed that EBX is a callee-saved register. The code is not particularly good. :-)
section .data
answer: dd 0
right: dd 0
wrong: dd 0
section .text
extern printf
extern scanf
global main
main:
push ebx
mov ebx, 1
.loop_start:
cmp ebx, 11
je .loop_end
push 1
push ebx
push .string0
call printf
add esp, 12
push answer
push .string1
call scanf
add esp, 8
inc ebx
cmp dword [answer], ebx
jne .wrong
push ebx
push .string2
call printf
add esp, 8
inc dword [right]
jmp .loop_start
.wrong:
push ebx
push .string3
call printf
add esp, 8
inc dword [wrong]
jmp .loop_start
.loop_end:
push dword [wrong]
push dword [right]
push .string4
call printf
add esp, 12
pop ebx
xor eax, eax
ret
section .data
.string0:
db "What is %d + %d? ", 0
.string1:
db "%d", 0
.string2:
db "right! ", 0
.string3:
db "Sorry, you're wrong. The answer is %d", 10, 0
.string4:
db "You got %d right and %d wrong.", 10, 0
Luckily for you, the printf function will do almost everything for you, even from assembly. You've probably read about the stack, and how you can call functions that take arguments that have been pushed on the stack. The same is true of printf. Push on the arguments in reverse order, so that the top thing on the stack is a reference to the format string. Then all you have to do is:
call printf
If I remember correctly, printf knows it has at least one argument, and that first argument (the format string) is the one that the stack pointer is pointing to. So then printf will scan through the format string and check if it needs to substitute in any of your other arguments, like i and i+1. Again, printf's doing this, you don't need to worry about it.
Hope this helps!
P.S. Re: the previous answers, usually it's not helpful to look at compiler-generated assembly code if you're trying to learn assembly. Even without optimizations enabled, the output's not meant for humans to read.
As an example , this line in C programming language:
printf("\n%d%s%d\n\n",num1," is not equal to ",num2);
is equivalent to:
printf PROTO arg1:Ptr Byte, printlist:VARARG
.data
msg1fmt byte 0Ah,"%d%s%d",0Ah,0Ah,0
msg1 byte " is not equal to ",0
num1 sdword 5
num2 sdword 7
.code
main proc
INVOKE printf, ADDR msg1fmt, num1, ADDR msg1, num2
ret

Resources