Q:

Assembling i386 code on x86_64

The following code does not work as expected:
.intel_syntax noprefix
.arch i386
.data
hello_world:
.ascii "Hello world!\n"
hello_world_end:
.equ hello_world_len, hello_world_end - hello_world
.text
.global _start
_start:
mov ebx, 1
mov ecx, hello_world
mov edx, hello_world_len
mov eax, 4
int 0x80

mov ebx, 0
mov eax, 1
int 0x80

When ran through:
as test.s -o test.o
ld test.o -o test
./test

It outputs nothing. When I change the line:
mov ecx, offset hello_world ; added offset

It works fine. I tried compiling the original code with --32 -march=i386 and linking with -m elf_i386 but it still outputs nothing.
$ uname -a
Linux ubuntu 3.2.0-38-generic #60-Ubuntu SMP Wed Feb 13 13:22:43 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

My guess is this happens because the memory model isn't flat like in i386. Can I emulate this somehow?

A:

It's not about the memory model.
In gas syntax mov ecx, hello_world means a read from memory address hello_world, as can be confirmed by checking the disassembly done with ndisasm:
00000000  BB01000000        mov ebx,0x1
00000005  8B0C25D4104000    mov ecx,[0x4010d4]
0000000C  BA0D000000        mov edx,0xd
00000011  B804000000        mov eax,0x4
00000016  CD80              int 0x80

What you want is to store the memory address of hello_world. In gas the way to accomplish that is mov ecx, offset hello_world, as can be confirmed from the disassembly:
00000000  BB01000000        mov ebx,0x1
00000005  B9D4104000        mov ecx,0x4010d4
0000000A  BA0D000000        mov edx,0xd
0000000F  B804000000        mov eax,0x4
00000014  CD80              int 0x80

By the way, another way to do load the memory address into a register is leaecx, hello_world.
Some other assemblers (such as NASM and YASM) have different syntax, and this difference may cause confusion, as can be illustrated with a small table:
gas                           NASM/YASM                ndisasm disassembly
mov ecx,hello_world           mov ecx,[hello_world]    mov ecx,[0x4010d4]
mov ecx,[hello_world]         mov ecx,[hello_world]    mov ecx,[0x4010d4]
mov ecx,offset hello_world    mov ecx,hello_world      mov ecx,0x4010d4

