• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1438
  • Last Modified:

I Get "invalid effective address" when compiling!

I need to code a calculator using NASM on Linux, and all it needs to do is  addition. When I compile, it keeps writing "invalid effective address" at line 81, which is in 'number' subfunction, the command 'add eax, [cl]'

What is the problem? Here is the code below:

segment .data

;no uninitialized data

segment .bss
acc1            resb 4
acc2            resb 4
display         resb 10
input_key       resb 1

;reserves needed amount of space for each

segment .text
        global _start

_start: call init
        call calc_display
        call keyb_input
        call dispatch

;functions needed to be called, in order

init:   sub [acc1], [acc1]
        ;makes acc1 equal to zero
        sub [acc2], [acc2]
        ;makes acc2 equal to zero
        sub [display], [display]
        ;makes display equal to zero
        ;goes back to where it elft off in start

calc_display:   mov eax, 4
                mov ebx, 1
                mov ecx, display
                mov edx, 10
                int 0x80
                ;code to print what is in display

keyb_input:     mov eax, 3
                mov ebx, 0
                mov ecx, input_key
                int 0x80
                ;code to save the key user presses into input_key

dispatch:       mov cl, [input_key]
                ;moves the contents of input_key into lower part of cx register
                ;to allow for the user's entry to be evaluated
                cmp cl, 0x21
                je exit
                ;if the user entered "!", then it skips right to exit
                cmp cl, 0x43
                je init
                ;if user enters "C", it goes back to init and resets  all values
                ;to zero
                cmp cl, 0x2B
                je plus
                ;if the user enters "+", it goes to plus
                cmp cl, 0x3D
                je equal
                ;if the user enters "=", it goes to equal
                cmp cl, 0x2F
                jle error
                cmp cl, 0x3A
                jge error
                ;if user enters values less than 0 or more than 9, it
                ;goes to error
                call number
                ;otherwise it goes to number
                loop calc_display

number: mov eax, [acc1]      
        ;moves whatever is in memory location acc1 to register eax
        shl eax, 1
        ;shifts whatever is in eax by 1 to the left, to allow for
        ;new numbers entered to be concatenated
        sub cl, 48
        ;turns what is in cl to digits
        add eax, [cl]
        ;concatenates what's in eax with cl
        mov acc1, [eax]
        ;stores the number in acc1
        mov [display], [acc1]
        ;stores the number in display
        call calc_display
        ;goes to calc_display to show latest value
        jmp keyb_input
        ;goes to keyb_input for next user entry

plus:   add [acc2], [acc1]
        ;adds what is in acc1 to acc2
        mov [display], [acc2]
        ;moves acc2 into display
        call calc_display
        ;goes to display to print latest value
        sub [acc1], [acc1]
        ;initializes acc1 in case more addition by user
        jmp keyb_input
        ;goes to keyb_input for next user entry

equal:  add [acc2], [acc1]
        mov [display], [acc2]
        call calc_display
        sub [acc1], [acc1]
        jmp keyb_input
        ;for the addition part, it does not need to be different than 'plus'

error:  jmp keyb_input
        ;goes back to keyb_input

exit:   mov eax, 1
        int 0x80
1 Solution
[cl] looks like you're trying to say "give nme the value at the address pointed to by the register "cl".

But there's no byte-register indirect instructions.

You probably wanted to say just "cl", not "[cl]"

Oh, BTW, I don't know if this is a NASM specific thing, but most every other PC assembler doesnt need the [brackets] around symbol names.

The 'add eax,[cl]' adds the contents of the memory location pointed to by cl to eax. However, cl is an 8-bit register and therefore not a valid pointer, so the assembler complains.

If you wanted to add an 8-bit register to a 32-bit one, write something like:

movzx ecx,cl
add eax,ecx

Some more things...

Memory/memory operations like 'sub [acc1],[acc1]' are not allowed. You can set a memory location to zero by using 'mov [acc1],dword 0', or some other constant. Since the assembler has no notion of size, you'll have to explicitly add byte, word or dword to indicate its size.

Reserving static data should also be done using the proper directive. If you want to reserve a dword, use RESD 1, not RESB 4.

As you probably know, system calls on Linux work using 'int 0x80' and take the system call number in eax (parameters go in ebx, ecx, edx, esi, edi). You can define the call numbers, so the code becomes much more readable. eg

%define SYS_EXIT 1
%define SYS_READ 3
%define SYS_WRITE 4

The full list of them is defined in the C include <asm/unistd.h>.
PAQed - no points refunded (of 125)

E-E Admin

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now