Author Topic: new to assembly  (Read 7157 times)

Offline sinth

  • Jr. Member
  • *
  • Posts: 2
new to assembly
« on: March 14, 2015, 06:05:49 AM »
this is my code.. but it is not taking input. I am new to assembly and not understanding what is the problem. please tell me
what I am doing wrong. and how I can correct it
Code: [Select]
%include "io.inc"
global _main
extern _printf
extern _scanf
section .data
prompt1: db 'enter the 1st no.', 0
prompt2: db 'enter the 2nd no.', 0
out_msg1: db 'you entered', 0
out_msg2: db 'the result is', 0
section .bss
input1: resd 1
input2: resd 1
section .text
;global _main
_main:
    mov ebp, esp; for correct debugging
    enter 0,0
    PUSHA;write your code here
    mov eax,prompt1
    call _printf;_string
    call _scanf;read_int
    mov [input1],eax
    mov eax,prompt2
    call _printf;_string
    call _scanf;read_int
    mov [input2],eax
    mov eax,[input1]
    add eax,[input2]
    mov ebx,eax
    ;dump_regs 1
    ;dump_mem 2, out_msg1,1
    ;**********************
    ;**********************
    mov eax,out_msg1
    call _printf;_string
    mov eax,[input1]
    call _printf;_int
    ;call printf_n1
   ; mov eax,[input2]
    ;call _printf;_int
    mov eax,out_msg2
    call _printf;_string
    mov eax,ebx
    call _printf;_int
    ;call print_n1
popa
mov eax, 0 ; return back to C
leave
ret
« Last Edit: March 14, 2015, 02:40:42 PM by Frank Kotler »

Offline shaynox

  • Full Member
  • **
  • Posts: 118
  • Country: gr
Re: new to assembly
« Reply #1 on: March 14, 2015, 04:55:19 PM »
Hello, you should respect this basic norm

Code: [Select]
Instruction        Destination, source        ; Comment

It makes it hard to read any code when code are not like this.

You miss upload the io.inc file and the instructions how to assemble it.

Every OS's function need initialize stack, so it needed to make sub esp, ... then add esp, ...

After for know how use/configure function, it's good to see how compiler do it, by see their asm file product during compiling (gcc -S).

I'm not familiarly to 32-bit, I code in x64 instead. So i'm not sure about stack initialization (sub   esp, 32), I copy that init from x64 use (sub rsp, 32).

I have put leave instruction in comment, cause I don't know how to use it.
And modify (out_msg1: db 'you entered', 0) to (out_msg1   db   "you entered %d + %d", 10, 0).

Here's the remake of your code:

Code: [Select]
; %include "io.inc"

; [global _main]
[extern printf]
[extern scanf]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[section .code use32]

_main:
; mov ebp, esp ; for correct debugging
; enter 0, 0
; pusha ; write your code here

sub esp, 44

mov [esp + 0], dword prompt1
call printf ; _string

mov [esp + 0], dword _d
mov [esp + 4], dword input1
call scanf ; read_int

mov [esp + 0], dword prompt2
call printf ; _string

mov [esp + 0], dword _d
mov [esp + 4], dword input2
call scanf ; read_int

add esp, 44

mov eax, [input1]
add eax, [input2]
mov [input3], eax

;dump_regs 1
;dump_mem 2, out_msg1,1
;**********************
;**********************

sub esp, 44

mov [esp + 0], dword out_msg1

mov eax, [input1]
mov [esp + 4], eax

mov eax, [input2]
mov [esp + 8], eax
call printf ; _string


; call printf_n1
; mov eax, [input2]
; call _printf ; _int

mov [esp + 0], dword out_msg2
call printf ; _string

mov [esp + 0], dword _d2
mov eax, [input3]
mov [esp + 4], eax
call printf ; _int

; call print_n1

add esp, 44

; popa

; mov eax, 0 ; return back to C
; leave
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[section .data use32]
prompt1 db "enter the 1st no. ", 0
prompt2 db "enter the 2nd no. ", 0
out_msg1 db "you entered %d + %d", 10, 0
out_msg2 db "the result is ", 0
_d db "%d", 0
_d2 db "%d", 10, 0
_s db "%s", 0
[section .bss use32]
input1 resd 1
input2 resd 1
input3 resd 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Assembling under windows:
Code: [Select]
nasm -f win32 source.asm
golink /console /entry _main source.obj  msvcrt.dll
« Last Edit: March 14, 2015, 07:03:19 PM by shaynox »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: new to assembly
« Reply #2 on: March 14, 2015, 06:18:37 PM »
Hi sinth,

Thanks for joining us! The first mistake might be not giving us enough information...
Code: [Select]
%include "io.inc"
This could be anything. I'm going to take a wild guess that it's the late Sivarama Dandimudi's include file, and you're probably supposed to link against his "io.obj". However, you appear to be trying to bypass his routines and replace them with calls to the C library. This could be done, but the interface is completely different.

Oh, wait! I'm mistaken. Dr. Dandamudi calls his include file "io.mac" not "io inc", so I'm completely off-base. Maybe you'd better start by telling us what "io.inc" is and where we might find it...

Blundering blindly ahead... regardless of what "io.inc" is, you still need to call the C libraries with the correct "calling convention". In 32-bit code (64-bit code is completely different!), we are expected to push the parameters on the stack, and we are expected to "clean up the stack" or "remove the parameters" after the function returns. Nothing actually gets "removed" - the parameters are still on the stack, but we've moved the stack pointer (esp) above them so the stack space can (and will) be re-used. The "last" or "rightmost" (as we would write them in C) gets pushed first, the "first" or "leftmost" parameter gets pushed last. In the case of _printf or _scanf the "first" (last pushed) parameter needs to be a "format string" - a zero-terminated(!) string including some "tokens" which tell our function what to do. The number of "tokens" tells our function how many more parameters to expect on the stack. We can probably get by with just a format string and one more parameter...

The C functions return the "result" in eax, but in this case it isn't the "result" we're looking for. I think _printf returns the number of bytes printed - it isn't very interesting. _scanf returns the number of items read. It may be worthwhile to check this value to make sure the pesky user entered something valid. For simplicity, we can "assume a well behaved user". If the pesky user enters "garbage" it's going to screw up the rest of our program royally. A "better" program would check!

So where were we?
Code: [Select]
; probably don't really need the include file
global _main
extern _printf
extern _scanf
section .data
prompt1: db 'enter the 1st no.', 0
prompt2: db 'enter the 2nd no.', 0
out_msg1: db 'you entered', 0
out_msg2: db 'the result is', 0

; some format strings...
string_fmt db '%s', 0
int_fmt db '%d', 0

section .bss
input1: resd 1
input2: resd 1
section .text
;global _main
_main:
    mov ebp, esp; for correct debugging
    enter 0,0
    PUSHA;write your code here
;    mov eax,prompt1
    push prompt1
    push string_fmt
    call _printf;_string
    add esp, 4 * 2 ; two parameters at 4 bytes each

; for _scanf, the parameter wants to be
; the address of an integer (dword) variable
; (where to put it)
; not the integer itself
; K&R calls this "the most common error"
    push input1
    push int_fmt
    call _scanf;read_int
    add esp, 4 * 2

; the "result" is not what we want!
;    mov [input1],eax

;    mov eax,prompt2
    push prompt2
    push string_fmt
    call _printf;_string
    add esp, 4 * 2

    push input2
    push int_fmt
    call _scanf;read_int
    add esp, 4 * 2
;    mov [input2],eax

; now we should have our two numbers
; add 'em up
    mov eax,[input1]
    add eax,[input2]

; copy answer to ebx
; because _printf is going to trash eax!
    mov ebx,eax

    ;dump_regs 1
    ;dump_mem 2, out_msg1,1
    ;**********************
    ;**********************
;    mov eax,out_msg1

    push out_msg1
    push string_fmt   
    call _printf;_string
    add esp, 4 * 2

    push [input1]
    push int_fmt
;    mov eax,[input1]
    call _printf;_int
    add esp, 4 * 2

; oops! we printed "you entered"
; and then only one number
; we may need a different format string for this
; ignore it for now?
    ;call printf_n1
   ; mov eax,[input2]
    ;call _printf;_int
;    mov eax,out_msg2

    push out_msg2
    push string_fmt
    call _printf;_string
    add esp, 4 * 2

;    mov eax,ebx

; remember that our answer is in ebx
    push ebx
    push int_fmt
    call _printf ;_int
    add esp, 4 * 2
    ;call print_n1
popa
mov eax, 0 ; return back to C
leave
ret

Well... that's untested. It may not even work. At the very least, it'll be "messy". It "may" be enough help so that you can fix it on your own...

If you continue to have trouble, come back here and give us more information. In general, we need to know:

1) What OS? (I'm guessing Windows - Linux doesn't use the underscores on "_main", etc.)

2) What command line did you give Nasm? (Nasm will do many different things. In some cases, you will need completely different code, depending on the output format.)

3) How did you link it? (if at all)

4) What did you "expect" to happen? (that seems obvious in this case - it isn't always)

5) What actually happened? (You say "no input". I'm guessing no output, either. "It doesn't work" is not very helpful. Segfault - what's Windows call it, "access violation"?  No output? Garbage output? Etc. There's a lot that can go wrong!)

Edit: Well I see shaynox has answered. Thanks, shaynox! Perhaps between the two answers you can figure something out.

Best,
Frank


Offline shaynox

  • Full Member
  • **
  • Posts: 118
  • Country: gr
Re: new to assembly
« Reply #3 on: March 14, 2015, 07:01:29 PM »
hmm yes you right, multiple answer is better than one, different point of view  :p (i'm also beginner to help other dev).