Live data from Hacker News

A fundamental introduction to x86 assembly programming

nayuki.io

61–70 of 78 posts

Re: A fundamental introduction to x86 assembly programming

#61
post #34

A very nice book about assembly programming is "Assembly Language Step-by-Step: Programming with Linux, 3rd edition" ( http://www.amazon.com/dp/0470497025 ). The nice thing about this book is that it guides the reader at understanding how the machine works first, and only then to assembly programming. The sad thing about this book is that it references 32 bit intel-compatible processors. My guess is that the original…

I found this book during my Google searches and really enjoy reading the author's website. Here's a comment [1] he made 3 years ago about a new version:

"Well, that isn’t completely my decision. When the publisher wants a new edition, they contact me, and then I begin writing. I don’t see a new edition on the horizon for a couple of years yet. Worse, I need additional pages to cover 64 bit issues, and the number of pages I have in the book is limited. Unless I can persuade the publisher to go beyond the 600-page mark, I’m going to have to eliminate other material to cover 64-bit assembly."

[1] http://www.contrapositivediary.com/?page_id=1808#ASMSBS3E

Re: A fundamental introduction to x86 assembly programming

#62
post #59
post #50

Earlier quoted context omitted.

x86-64 is really oriented around integer values being 64-bits. For example, 32-bit operations will zero-extend the result to write the full 64-bit integer register. The ABI also assumes integral values are promoted to 64-bits and the stack is 64-bit aligned on calls. That said, as long as you keep RSP aligned you can do whatever you want. Consider this code: extern void value(int* a, int* b, int* c); int main() { int…

Almost correct. If you want to call C code conforming to the x86-64 SYSV ABI, RSP needs to be aligned to 16 bytes when you execute the call . If the code you generate never calls alien code, 8 byte alignment is enough. Since 8 bytes are occupied by return address pushed by the call which started your function, you need to decrease RSP by further 8, 24, 40, 56, 72, ... bytes before calling code generated by others. Re…

Ah, good point. I forgot about the return address.

Re: A fundamental introduction to x86 assembly programming

#63
post #11
post #7

Anytime I see anything names my-asm or mini.asm or anything like that, it instantly yanks me back to college. We had this awesome teacher who had been at DEC for decades and taught at night. He'd bring in chunks of core memory, and tell us all about the old days in between course work. God I loved that class.

I'm reading Hackers by Stephen Levy right now and DEC's pdp computer era as described seems like a real golden age. I'd enjoy more history book recommendations along this line if anyone knows of some

Specifically about British computing is Electronic Dreams (Tom Lean) (disclosure: I went to university with the author).

The Cogwheel Brain: Charles Babbage and the Quest to Build the First Computer (Doron Swade) is also an interesting read, especially as Babbage's ideas were eventually vindicated when the Science Museum built it in the 1990s and it worked.

Re: A fundamental introduction to x86 assembly programming

#64
post #31
post #29

Earlier quoted context omitted.

That's less of an assembly issue and more of a compiler/calling convention issue. Assembly allows you to pass parameters on the stack or in registers. Calling conventions simply define a protocol for doing this consistently.

Actually Id'd say that it's mostly the crappy processor design issue: for example, UltraSPARC has 32 physical registers in 32-bit mode, and 256 virtual registers (through register windows, specifically designed for compilers). Even Motorola 68000 with eight general purpose address registers and eight general purpose data registers is far more elegant than a 32-bit four register intel CPU. intel CPU is just crap from…

While x86 is arguably pretty ugly, I think you're being unfair.

> ... far more elegant than a 32-bit four register intel CPU.

I count eight: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP.

x86 has also advantage of supporting arbitrary immediate values, so you don't need to allocate registers just for constants.

Re: A fundamental introduction to x86 assembly programming

#65
post #34

A very nice book about assembly programming is "Assembly Language Step-by-Step: Programming with Linux, 3rd edition" ( http://www.amazon.com/dp/0470497025 ). The nice thing about this book is that it guides the reader at understanding how the machine works first, and only then to assembly programming. The sad thing about this book is that it references 32 bit intel-compatible processors. My guess is that the original…

amd64 is essentially a superset of the 32-bit version, and so it makes sense to understand 32-bit first. Actually, it's more like a half-64-bit extension because not everything is consistently 64-bit and a lot of things like operand sizes and registers actually default to being 32 bits.

That's true. I started with 16b and transitions to 32b and 64b were pretty straightforward. It's mostly just registers becoming wider.

Re: A fundamental introduction to x86 assembly programming

#66
post #15

> The way the x87 FP stack works is a bit weird, and these days it’s better to do floating-point arithmetic using xmm registers x87 allows to do calculations in extended precision, i.e. word width is 80 bits. SSE is limited to double precision (64-bit words). Also FPU has some advanced math instructions, like sin, cos, tan, exp, etc., and these operations will be available in AVX512F.

Have fun debugging arithmetic difference resulting from spilling an intermediate result to memory and rounding to 64bit value vs. not spilling and keeping the intermediate value as 80 bits.

FST/FLD can store/load full 80 bits if you need such precision. No problem whatsoever.

Re: A fundamental introduction to x86 assembly programming

#67
post #64
post #31

Earlier quoted context omitted.

Actually Id'd say that it's mostly the crappy processor design issue: for example, UltraSPARC has 32 physical registers in 32-bit mode, and 256 virtual registers (through register windows, specifically designed for compilers). Even Motorola 68000 with eight general purpose address registers and eight general purpose data registers is far more elegant than a 32-bit four register intel CPU. intel CPU is just crap from…

While x86 is arguably pretty ugly, I think you're being unfair. > ... far more elegant than a 32-bit four register intel CPU. I count eight: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP. x86 has also advantage of supporting arbitrary immediate values, so you don't need to allocate registers just for constants.

eax is the accumulator register, ebx the base register, ecx the counter register, edx the data register, esi is the source index, edi is the destination index, ebp is the base pointer, and esp is the stack pointer.

When I originally wrote four general purpose registers, I had eax, ebx, ecx and edx in mind, but after fully listing them above, I revise my earlier statement: the x86 assembler has two general purpose registers. Crappy processor architecture with lots of specialized registers, but too few general purpose ones.

Compared to MOS 6502, Motorola MC680##, or SPARC, only the eax and edx are really general purpose registers -- even mentioning ecx, the counter register, would be iffy.

Re: A fundamental introduction to x86 assembly programming

#68
post #67
post #64

Earlier quoted context omitted.

While x86 is arguably pretty ugly, I think you're being unfair. > ... far more elegant than a 32-bit four register intel CPU. I count eight: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP. x86 has also advantage of supporting arbitrary immediate values, so you don't need to allocate registers just for constants.

eax is the accumulator register, ebx the base register, ecx the counter register, edx the data register, esi is the source index, edi is the destination index, ebp is the base pointer, and esp is the stack pointer. When I originally wrote four general purpose registers, I had eax, ebx, ecx and edx in mind, but after fully listing them above, I revise my earlier statement: the x86 assembler has two general purpose reg…

6502 has only accumulator anyways. X and Y are not general purpose.

68k is pretty nice, d0-d7 registers are indeed interchangeable. Of course a0-a7 are just for addressing, I think a7 was usually stack pointer.

SPARC I've never programmed, so no comments about it.

I've written x86 code in the past (20 years ago) using all 8 registers for general purpose task -- yes, even ESP. It was faster that way to implement a texture mapper. Ugly but fast.

Those 8 x86 registers are mostly general purpose, apart from some exceptions.

Multiplication was the only annoying one, getting result in EAX:EDX.

I always succeeded making x86 do whatever I wanted, despite some limitations with register use.

Re: A fundamental introduction to x86 assembly programming

#69
post #66

Earlier quoted context omitted.

Have fun debugging arithmetic difference resulting from spilling an intermediate result to memory and rounding to 64bit value vs. not spilling and keeping the intermediate value as 80 bits.

FST/FLD can store/load full 80 bits if you need such precision. No problem whatsoever.

I've never seen anyone store 10 byte IEEE-754 values in memory.

People store doubles, and people get upset when compiler optimizations (like when to spill from registers to memory and whether to use one or two instructions for multiply-and-add) change not just the performance but also the result of computations.

Re: A fundamental introduction to x86 assembly programming

#70

If you want to learn x86 assembly, I recommend one of my favorite books Programming From The Ground Up: http://savannah.nongnu.org/projects/pgubook/ (free pdf!) This is a practical book and teaches assembly programming on Linux. Author Jonathan Bartlett wrote this book because he was frustrated to no end with the existing books. At the end of them he could still ask, "How does the computer really work?" and not have…

This book was what made C click for me (in the few chapters I digested way back when). I actually stopped reading twice because I suddenly understood something that had blocked my progress in C, and went on my way for a year or two until I decided to pick the book up again.

For a quick idea of what ASM can look like if you build up the foundations step-by-step, and understand what you're working with:

    .include "record-def.s"
    .include "linux.s"
    #PURPOSE: This function reads a record from the file descriptor
    #
    #INPUT: The file descriptor and a buffer
    #
    #OUTPUT: This function writes the data to the buffer
    # and returns a status code.
    #
    #STACK LOCAL VARIABLES
    .equ ST_READ_BUFFER, 8
    .equ ST_FILEDES, 12
    .section .text
    .globl read_record
    .type read_record, @function
    read_record:
    pushl %ebp
    movl %esp, %ebp
    pushl %ebx
    movl ST_FILEDES(%ebp), %ebx
    movl ST_READ_BUFFER(%ebp), %ecx
    movl $RECORD_SIZE, %edx
    movl $SYS_READ, %eax
    int $LINUX_SYSCALL
    #NOTE - %eax has the return value, which we will give back to our calling program
    popl %ebx
    movl %ebp, %esp
    popl %ebp
    ret
  
With the definitions in place, its like a whole different language.

For reference, the definitions are simply a text file with contents similar to:

    #System Call Numbers
    .equ SYS_EXIT, 1
    .equ SYS_READ, 3
    .equ SYS_WRITE, 4
    .equ SYS_OPEN, 5
    .equ SYS_CLOSE, 6
    .equ SYS_BRK, 45
  
Or (record-defs.s in the example) clearly describing the data with:

    .equ RECORD_FIRSTNAME, 0
    .equ RECORD_LASTNAME, 40
    .equ RECORD_ADDRESS, 80
    .equ RECORD_AGE, 320
    .equ RECORD_SIZE, 324
  
This book opened my eyes to the concrete, data driven nature of the problems I'm trying to solve, at an atomic level. It somehow dispelled all the magic behind programming, while exciting the mechanical side of my brain, leaving me with that "its just a machine, I can solve any problem if I just trace things patiently until I understand the parts and how they interact".
Post reply on HN