14 ms·
“Hello World” in assembly language on Linux
- 2bluesc 12y agoWent to see the printf or puts implementation rather then just calling a library function. Then saw Intel assembly and reminded myself why I've never wrestled with it.
- mitchi 12y agoThis is the GNU assembler AT&T syntax though, which is known to be horrendous. Other assemblers have much nicer syntax.
- userbinator 12y agoAgreed; most programmers I know who write a lot of x86 Asm tend to stick with the Intel syntax. I've never found the "it's easier to parse" argument for AT&T syntax particularly convincing, especially as GAS is written in C while some of the Intel syntax assemblers existing at the time were themselves written in x86 Asm. Neither is the "it makes it more consistent with the other arch's assemblers" - just look at GAS' syntax for MIPS and ARM. It seems to me like someone was really obsessed with the SPARC syntax (which I find roughly as horrendous.) http://x86asm.net/articles/what-i-dislike-about-gas/ http://x86asm.net/articles/what-i-dislike-about-gas/
- Narishma 12y agoI don't think either syntax is nicer than the other. It's just a matter personal preference and familiarity.
- cbd1984 12y agoIntel syntax has more intuitive memory access syntax: AT&T syntax: movl mem_location(%ebx,%ecx,4), %eax Intel syntax: mov eax, [ebx + ecx*4 + mem_location] The other differences are minor compared to that, IMHO. https://en.wikipedia.org/wiki/X86_assembly_language#Syntax https://en.wikipedia.org/wiki/X86_assembly_language#Syntax
- lokedhs 12y agoI can agree with most of that, except for the fact that Intel arguments are backwards. That throws me off every time. I don't know of any other assembler syntax that uses that argument order.
- oso2k 12y agoFor me, I remember the notation by correlating it to its "high-level" equivalent. mov eax, [ ptr ] is like eax = *ptr; // or, eax = ptr[ 0 ]; The offset/multiplier memory addressing format for AT&T syntax was always more troubling for me. Coming from a TASM/MASM/NASM/PASCAL/x86 background first, it felt "icky" to put offsets outside of the "brackets" (or parenthesis, as it were) [0][1]. [0] https://github.com/lpsantil/rt0/blob/master/src/lib/00_start.c#L14 https://github.com/lpsantil/rt0/blob/master/src/lib/00_start... [1] https://github.com/lpsantil/rt0/blob/master/src/lib/00_start.c#L21 https://github.com/lpsantil/rt0/blob/master/src/lib/00_start...
- userbinator 12y agoStandard ARM, MIPS, PowerPC, x86, and Z80 Asm syntax all have the destination on the far left. 68k, Alpha, PDP-11, SPARC, and VAX have the destination on the far right. The order is probably as contentious as the great endianness debate, but I think one of the most awkward parts of having src, dst order is that subtraction looks backwards. I prefer dst, src because it corresponds closely with the direction of assignment in higher-level languages: op a, b, c ; a = b op c op a, b ; a op= b
- giancarlostoro 12y agoIs it just me or is that font way too large?
- emodendroket 12y agoSure would be nice if your Web browser allowed you to make text bigger or smaller whenever you pleased.
- giancarlostoro 12y agoAs aw3c2 mentioned, it's the spacing, which I didn't realize, so even if I can shrink the font (which yes I know I can, but why should I be forced to change how the web page was intended to be viewed?) but then it'll be unreadable if I want to cover more ground than having to scroll because of all the comment.
- throway1122334 12y agoYeah, line height is one of the biggest problems in web design. I have to change it on many text-heavy pages to make it readable. It's not ideal, and should really fall upon designers to fix, but a workaround (in Chrome or Firefox) is to edit the page's source (either with Chrome webtools or Firebug) and add a line-height attribute to <p> or whatever tag or class is most applicable, and set it to something like 125% or 135%. Usually results in a much more readable page.
- aw3c2 12y agoI think it's the line-height, super hard to keep track for me.
- dmuth 12y agoAs someone who hasn't touched assembly in over a decade but had been meaning to get back into it, this post actually gives me a good starting point. Thanks for sharing it!
- pjmlp 12y agoThe next step would be to replace the printf() call by a call to write() and remove the dependency to libc.
- shanemhansen 12y agoI'd love to see a version of this done using the linux amd64 syscall abi. I've written similar programs for 32bit linux (I know the syscall instruction by heart: int 0x80), but I understand 64bit is more complex.
- nitrogen 12y agoSounds complicated, if AMD and Intel both use different instructions for system calls: http://wiki.osdev.org/Sysenter http://wiki.osdev.org/Sysenter http://articles.manugarg.com/systemcallinlinux2_6.html http://articles.manugarg.com/systemcallinlinux2_6.html
- oso2k 12y agosyscall is the standard ABI for a 64-bit kernel in Long Mode [0]. [0] http://wiki.osdev.org/SYSENTER#Compatibility_across_Intel_and_AMD http://wiki.osdev.org/SYSENTER#Compatibility_across_Intel_an...
- oso2k 12y agoThe syscall version isn't much more complex. You can compare the syscall ABIs here [0] [0] http://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_syscall http://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_L...
- tbirdz 12y agoI don't know if I would call it harder, it's just a bit different is all. Here you go: ; Hello World, linux x86_64, nasm syntax section .rodata ; Begin read only data section hello: db "Hello, World",0x0a ; String, 0x0a is \n hello_len equ $-hello ; $ is current address, length is address after string - address of start of string section .text ; begin code section global _start ; export _start so the linker can see it _start: ; program entry point mov rax, 1 ; write(2) syscall number mov rdi, 1 ; stdout mov rsi, hello ; string address mov rdx, hello_len ; string length syscall ; execute the write syscall mov rax, 60 ; exit(2) syscall number mov rdi, 0 ; exit status syscall ; execute the exit syscall
- Alupis 12y agoSmidge simpler and uses only kernel routines # as hello.S -o hello.o # ld hello -o hello # ./hello .data # .data section starts msg: .ascii "Hello, World!\n" # msg is ASCII chars (.ascii or .byte) len: .int 14 # msg length is 14 chars, an integer # .int 32 bits, .word 16 bits, .byte 8 bits .text # text (instruction code) section starts .global _start # _start is like main(), .global means public # public symbols are for linker to link into runtime _start: # _start starts here movl len, %edx # value 14 copied to CPU register edx movl $msg, %ecx # memory addr of msg copied to CPU register ecx movl $1, %ebx # file descriptor 1 is computer display movl $4, %eax # system call 4 is sys_write (output) int $128 # interrupt 128 is entry to OS services movl $1, %eax # system call 1 is sys_exit (prog exits) movl $77, %ebx # status return (shell command: "echo $?" to see it) int $128 # call OS to do it via interrupt #128
- jheriko 12y agothis is a much better example since it does away with the needless complexities, and is a good starting point for looking at interrupts and how they are used in this environment... since their importance isn't hidden behind a layer of needless logic and a c library call.
- jheriko 12y agoi'm not sure if this is good. for one it uses more code than necessary to do things it doesn't need to do (checking arguments, storing the string in two pieces) for another its just not in the spirit of hello world, which is supposed to show something that just displays hello world. its making assembly look harder than it is.
- hannob 12y agoIt's been a while since I did any assembler, but one thing I remember: If you seriously want to write anything GAS may not be your best option. nasm has a much saner syntax (and if you ever happened to have used tasm or masm it's much more similar to that).
- mpu 12y agoSyntax, in assembly, is the least of your problems.
- tux3 12y agoI couldn't disagree more. Having tried the perfection that is MASM, I'm always disappointed by what NASM lacks in comparison and I'm not at all comfortable with GAS. Choosing a good assembler, an assembler that you like, that you're comfortable with, is critical.
- alecco 12y agoYASM might be a better choice if you are starting from scratch.
- ndesaulniers 12y agoSee also: http://nickdesaulniers.github.io/blog/2014/04/18/lets-write-some-x86-64/ http://nickdesaulniers.github.io/blog/2014/04/18/lets-write-...
- Narishma 12y agoIs it me or is his explanation of call and ret backwards? Shouldn't call decrement %rsp and ret increment it since the stack grows downward?
- yomritoyj 12y agoOP here. You are right. Fixed now.
- SFjulie1 12y agoHello world example is a great misdirection. Heavy lifting is done by an external routine being called. That does not make you learn assembly language. ASM is about interrupt (bottom half), calling other piece of assembly, saving and restoring the registers, and above all mastering the mov, and the art of deciphering how registers are used. This is only just assembly quiche programming.
- iN7h33nD 12y agoHow would someone go about learning assembly these days? I have seen quite a few assembly posts for starting out but never know where to go from there.
- collingreene 12y agoAssembly Language step by step by Jeff Duntemann remains one of my favorite books overall (not just programming, not just computers). It was updated in the last few years and the 3rd edition remains quite good.
- alfiedotwtf 12y agoDefinitely a great book! Once you're done, check out the MindShare books (especially their book on protected mode).
- collingreene 12y agoNice, these look superior to the intel books (which intel graciously printed then mailed to me for free like 10 years ago, go intel!). Ill check them out.
- netheril96 12y ago> An integer or pointer return value is returned in %ebx. Is this a typo? The return value is stored in %rax or %eax, not %ebx.