First of all I shall say kudos to Richard Blum, he did an excellent job writing this book and I'm glad there's finally a good book for GAS / AT&T Syntax assembly. Not only that but also this is about the best modern assembly book out there and it focuses on the IA-32 architecture. Note that this book is definitely not for beginners, you should know C and binary arithmetic (numerical systems and bitwise operations) before delving in this book. Anyhow with the existence of this book I'm tempted to write an AT&T syntax assembler of GAS quality for Windows, I'll try to do it when I get some spare time from my current projects and work. For now...
You can use this book with Windows, not only Linux, here's how:
1) You need the GNU tools for windows (which include the Assembler (GAS), the Linker (LD), the C/C++ Compilers (GCC/G++), the debugger (GDB), amongst other goodies). The windows port is called MinGW (Minimalist GNU for Windows), you can download them directly from:
http://www.mingw.org/download.shtml or get the C/C++ IDE called Dev-C++ which uses the MinGW tools/compilers and the as.exe ld.exe gcc.exe should be in the C:\Dev-Cpp\bin folder.
2) How to Assemble and Link with MinGW?
Now after assembling a few samples in C, I figured the absolute minimum (the template) for assembling in MinGW's GAS is the following:
Code:
.section .text
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
#code in here
leave
ret
You need to push the stack data pointer and move the stack pointer to it in order for it to work, otherwise the program will crash in windows. Save the code as 'template.s' and to assemble and link it just use: gcc -o template.exe template.s
3) How to Assemble and Link the first sample CPUID from Chapter 4?
Windows does not support the Linux Kernel system calls or its interrupts so we cannot use the
Code:
movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80
instructions for writing a string on the console. Our best option here is to substitute I/O with C Standard Library functions like printf to get output. So instead of that whole mess we just move $output to the stack pointer (%esp) register and call _printf. So our previous code becomes:
Code:
movl $output, (%esp)
call _printf
This means that we also don't need:
Code:
movl $1, %eax
movl $0, %ebx
int $0x80
for exiting our application, instead we just do a
And this is the end result:
Code:
#****************************************
#cpuid.s sample
#ported to win32 by Noone9
#it runs on MinGW's GNU gas/gcc
#****************************************
.section .data
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
.section .text
.globl _main
_main:
#****************************************
# Needed in Windows
#****************************************
pushl %ebp
movl %esp, %ebp
#****************************************
# CODE GOES HERE
#****************************************
movl $0, %eax
cpuid
movl $output, %edi
movl %ebx, 28(%edi)
movl %edx, 32(%edi)
movl %ecx, 36(%edi)
movl $output, (%esp)
call _printf
leave
ret
Now just do a 'gcc -o cpuid.exe cpuid.s' to assemble and link the code.
4) Assemble and link CPUID2, the second sample doesn't need any major change, just change printf to _printf and end to _end, C library functions require an underscore first.