TheFrenchPlays Hd Micraftn TheFrenchPlays Hd Micraftn - 4 months ago 12
Linux Question

Bss section --> invalid combination of operands

i have got a Problem programming nasm under Linux.

my problem is

/home/maximilian/Schreibtisch/Programmierung/meinCompiler/var2.asm:6: warning: character constant too long
/home/maximilian/Schreibtisch/Programmierung/meinCompiler/var2.asm:6: error: invalid combination of opcode and operands
/usr/bin/ld: cannot find /home/maximilian/Schreibtisch/Programmierung/meinCompiler/var2.o: Datei oder Verzeichnis nicht gefunden


my nasm Code:

section .data

section .text
global _start:
_start:
mov HALLO, "HALLO"
mov eax, 1
mov ebx, 0
int 0x80

section .bss
HALLO: resb 4


could anyone Please help me?

I have searched about this topic, but haven't found anything comprehensive for a NASM-newb

I hope, you can respond me,

tfphd

Answer

If you would declare the memory content in .data:

section .data
HALLO: db 'HALLO'

you would create:

  • from point of compilation: a symbol named HALLO, which contains address pointing to the 'H' character
  • from point of linux executable: 5 bytes long array containing bytes 72,65,76,76,79, in read-write initialized (once by loading executable) memory area.

So now you can do things like:

mov   eax,HALLO                    ; loads value of symbol HALLO into register eax
  ; value of symbol HALLO is address of that array
mov   DWORD [eax+2],0x454D504C     ; writes number over 'LLO?' in that array
  ; creating string 'HALPME' in memory at address HALLO
  ; BUG: notice how 1 character is overwritten after the original array
  ; this may overwrite and destroy some other important value in .data

If you would create this in .rodata section, it wouldn't be wise to try to modify it. See NASM sections manual for details.

If you create it in .bss, the array should be uninitialized, like you did originally, loading the executable into memory will just reserve that space, but not initialize it.

You can't do mov HALLO, "HALLO", that's not how x86 assembly works. The closest thing to it is mov DWORD [HALLO],'HALL' mov BYTE [HALLO+4],'O'. You can't store 5 bytes with single instruction in 32b mode.

So if you want to set some memory array to some initial value string, either use .data section, and after the initial text bytes add line times 64 db 0 to enlarge it by 64 bytes (so you can overwrite it with longer string later). - if you want it initialized once per executable run.

Or put that 'HALLO' into .rodata, with some mechanism marking the length of string (either having it as number 5 somewhere, or add 6th byte after O with 0 or some other terminator ($ is used in DOS for int 21h). And create long enough buffer in .bss like stringBuffer: resb 69. And then every time you want to set it to 'HALLO', you have to copy 5 bytes from address HALLO to address stringBuffer.

BTW, notice how naming value 'HALLO' with symbol HALLO is super awkward in such example, as now you have to pay extra attention to recognize where I'm talking about label (symbol/address), and where I'm using it as literal value (bytes).

Overall, if you are just starting with ASM, move from strings to numbers (and don't try to output them, just run in debugger and watch the register/memory values trough debugger).

After you get familiar with byte/word/dword, addresses, and basic arithmetic instructions, then check how strings are encoded in memory (ASCII/UTF-8/UTF-16), and how it looks from the position of number machine (CPU). Or follow any nasm tutorial, it will very likely start with some "hello world" display, which will probably not explain into depth, why that magic db 'hello world',10 works as string with int 80h (eax,4;...).

Comments