This depends massively on the operating system you target (or or BIOS or bare metal), the executable format you target, and the assembler you use.
The first example you posted is for MS-DOS .COM programs, the second for MS-DOS .EXE programs, and I assume both are using the Microsoft® assembler.
If you want to use the GNU assembler (e.g. on MirBSD or GNU/Linux) to target i8086 MS-DOS .COM programs, you can use this:
.intel_syntax noprefix
.code16
.text
.globl _start
_start: mov ah,9
mov dx,offset msg
int 0x21
/* exit(0); ← this is a comment */
mov ax,0x4C00
int 0x21
msg: .ascii "Hello, World!\r\n$"
Compile this file (hw.S
) with:
$ gcc -c -o hw.o hw.S
$ ld -nostdlib -Ttext 0x0100 -N -e _start -Bstatic --oformat=binary -o hw.com hw.o
I tested the result in DOSBOX under MirBSD/i386, and looked at it in hexdump to see that it’s correct.
In contrast to the other solutions, you do not define the origin (org) in the assembly file but on the linker (ld) command line, here.
I’ve also got an example targetting raw x86 BIOS and another one (bootsector for blocklists) and another one (bootsector for *.tar archives), in case you’re interested; they need different origins though, and they require an i386 CPU even though they use the 16-bit mode only.
You can’t do *.EXE files that way.
ELKS is also an interesting i8086 target, but I haven’t done much with it yet. Do make sure you get a GNU as version new enough to know the .intel_syntax noprefix
mode though.