I'm attempting to get ahead of my schooling by teaching myself assembly. I created a Hello World that prints the entire string in one go, and as far as I can tell, it works fine:
global _start
section .data
hello db "Hello World", 0xa
section .text
_start:
mov eax, 4 ; System call code. 4 = Write
mov ebx, 1 ; Descriptor to write to. 1 = stdout
mov ecx, hello ; String
mov edx, 12 ; Length of string
int 0x80 ; System call
mov eax, 1 ; System call code. 1 = Exit
mov ebx, 0 ; Exit code
int 0x80
This prints "Hello World". For kicks though, I decided to try and split the print up, and print "hello" using one system call, then print "world" after as a separate call:
global _start
section .data
hello db "Hello"
world db " World", 0xa
section .text
_start:
mov eax, 4
mov ebx, 1
mov ecx, hello ; First half
mov edx, 5 ; First half length
int 0x80
mov ecx, world ; Second half
mov edx, 7 ; Second half length
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Unfortunately though, this only prints "Hello"
. It seems like it's outright skipping the second interrupt. Playing around with it, I found that if I make the length argument large enough to accommodate the entirety of both strings, it "works":
. . .
mov eax, 4
mov ebx, 1
mov ecx, hello
mov edx, 12 ; Large enough for both strings
int 0x80
mov ecx, world
mov edx, 0
int 0x80
. . .
This correctly prints "Hello World". If I run this in gdb
, I can see that in this case, the first system call prints the entire string; it isn't divided. I'm guessing this is because the strings are stored next to each other in memory, and I'm overflowing from hello
into world
.
Why can't I have two separate write system calls to print two separate strings in this case though?
Running on ParrotOS, in VMWare.
Assembled and linked using:
nasm -f elf64 -g -F dwarf helloWorld.asm
ld -m elf_x86_64 helloWorld.o
First chunk of lscpu
:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 43 bits physical, 48 bits virtual
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 2
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 142
Model name: Intel(R) Core(TM) i5-8365U CPU @ 1.60GHz
. . .