Author Topic: Strange beginner issues.  (Read 12665 times)

Offline Brodie337

  • New Member
  • Posts: 1
Strange beginner issues.
« on: March 18, 2011, 10:53:26 AM »
Hi there, I'm learning Assembler as a part of my uni degree, and I've run into a few issues. I understand NASM to be similar in use to YASM, so I though here might be the best place to post this.
Code: [Select]
section .bss

mychar  resb    1

section .data
cr      db      0x0a
msg     db      'string<cr> : '
len     equ     $ - msg
i db 0
msg2    db      'Too Long! ' ; sequence of ASCII characters
len2    equ     $ - msg2 ; number of characters

section .text
        global _start

_start:

        mov     edx, len
        mov     ecx, msg
        mov     ebx, 1
        mov     eax, 4
        int     0x80

jmp reading


counter:

mov ecx, i
add ecx, 1

reading:

        mov     edx, 1
        mov     ecx, mychar
        mov     ebx, 0
        mov     eax, 3
        int     0x80


        mov     al, [mychar]
        cmp     al, [cr]
        jne     counter        ; jump if mychar != cr

mov al, i
cmp al, 10
jg toolong
jmp finish
toolong:

;print out
        mov     edx, len2
        mov     ecx, msg2
        mov     ebx, 1
        mov     eax, 4
        int     0x80
finish:
        mov     eax, 1         ; exit()
        int     0x80


Produces this:
Code: [Select]
[bmaguire @ Ass1] > yasm -f elf input.asm
[bmaguire @ Ass1] > ld -o input input.o
input.o: In function `no symbol':
input.asm:(.text+0x44): relocation truncated to fit: R_386_8 against `.data'


I just can't see what I'm doing wrong?
« Last Edit: March 18, 2011, 11:04:45 AM by Brodie337 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Strange beginner issues.
« Reply #1 on: March 18, 2011, 12:56:56 PM »
Well....

Code: [Select]
mov al, i

What does this do? It mov's (or attempts to) the address of i into al. The address of i is a 32-bit quantity, and won't fit into an 8-bit register, thus the problem. What you actually want to do here is mov the "[contents]" of i into al:

Code: [Select]
mov al, [i]

That change alone will shut Nasm/Yasm up, and your program will assemble and link without complaint, but it still won't work as intended. You do essentially the same thing earlier...

Code: [Select]
section .bss

mychar  resb    1

section .data
cr      db      0x0a
msg     db      'string<cr> : '
len     equ     $ - msg
i db 0
msg2    db      'Too Long! ' ; sequence of ASCII characters
len2    equ     $ - msg2 ; number of characters

section .text
        global _start

_start:

        mov     edx, len
        mov     ecx, msg
        mov     ebx, 1
        mov     eax, 4
        int     0x80

jmp reading


counter:

mov ecx, i
add ecx, 1

Again, you want "[contents]" of memory, not the address. This time, it's going into a 32-bit register, so ld doesn't whine, but it isn't really what you want to do. "[ i ]" (spaces required to keep the forum software from switching us to italics!) is only a byte long, so you're mov'ing the first couple (three) characters of "Too long" into ecx. This doesn't actually do any harm, but it isn't "right". You probably want to use an 8-bit register here - cl will do...

Having incremented the count in cl (or ecx), what do you do with it? Nuthin'!!! You probably want to store the new value back into "[ i ]", eh? If you do:

Code: [Select]
mov [i], ecx

... it will clobber the first bytes of "Too long". Since adding 1 won't change these upper bytes (until you get to 255 in [ i ], which you don't, you won't see any problem, but it's still not "right". Use an 8-bit register... or... we can manipulate the value in memory without mov'ing it into a register and back. If you do:

Code: [Select]
add [i], 1

... since there's no 8- or 32-bit register involved, Nasm doesn't know "how big of a 1" to add, it'll complain about "operation size not specified". Some assemblers (noteably Masm) do remember that you said "i" was "db" and will do the right thing, but Nasm (and, I think, Yasm) has amnesia and needs to be told:

Code: [Select]
add byte [i], 1
;or
add [i], byte 1

Either way should work. If you're more comfortable with a register, use that. There are cases where we need to use a register... if we wanted to move [ i ] into [j], say...

Code: [Select]
mov byte [j], [i] ; <- RONG!

Sorry, no such instruction! We need to use a register:

Code: [Select]
mov cl, [i]
mov [j], cl

That doesn't apply to your code, but I though I'd mention it, since we're on the subject. Back to your code...

Code: [Select]
reading:

        mov     edx, 1
        mov     ecx, mychar
        mov     ebx, 0
        mov     eax, 3
        int     0x80


        mov     al, [mychar]
        cmp     al, [cr]
        jne     counter        ; jump if mychar != cr

mov al, i ; <- here's the "truncate" error
cmp al, 10
jg toolong
jmp finish
toolong:

;print out
        mov     edx, len2
        mov     ecx, msg2
        mov     ebx, 1
        mov     eax, 4
        int     0x80
finish:
        mov     eax, 1         ; exit()
        int     0x80

I think with those minor changes, your code will work as intended. Good job!

Best,
Frank