English Persian
Chapter 11. x86 Assembly Language Programming
This chapter does not explain the basics of assembly language. There are enough resources about that (for a complete online course in assembly language, see Randall Hyde's http://webster.cs.ucr.edu/[Art of Assembly Language]; or if you prefer a printed book, take a look at Jeff Duntemann's Assembly Language Step-by-Step (ISBN: 0471375233). However, once the chapter is finished, any assembly language programmer will be able to write programs for FreeBSD quickly and efficiently. این فصل مبانی زبان همگذاری (اسمبلی) را توضیح نمی‌دهد. منابع بسیاری برای آن منظور وجود دارند (برای درسی کاملاً‌ برخط در زبان اسمبلی، <link xlink:href="http://webster.cs.ucr.edu/">Art of Assembly Language</link> از Randall Hyde را ببینید؛ یا اگر ترجیحتان بر کتاب چاپی است، نگاهی به Assembly Language Step-by-Step (ISBN: 0471375233) نوشتهٔ Jeff Duntemann بیندازید). هرچند، همین‌که این فصل به پایان رسد، هر برنامه‌نویس زبان اسمبلی قادر به نوشتن سریع و بهینهٔ برنامه‌های FreeBSD خواهد شد.
Copyright (R) 2000-2001 G. Adam Stanislav. All rights reserved. حق نشر © ۲۰۰۰-۲۰۰۱ G. Adam Stanislav. تمامی حقوق محفوظ است.
Two very different assemblers are available for FreeBSD. One is man:as[1], which uses the traditional UNIX(R) assembly language syntax. It comes with the system.
The other is /usr/ports/devel/nasm. It uses the Intel syntax. Its main advantage is that it can assemble code for many operating systems. It needs to be installed separately, but is completely free.
This chapter uses nasm syntax because most assembly language programmers coming to FreeBSD from other operating systems will find it easier to understand. And, because, quite frankly, that is what I am used to.
The standard man:ld[1] linker comes with FreeBSD. It works with the code assembled with either assembler.
By default, the FreeBSD kernel uses the C calling convention. Further, although the kernel is accessed using `int 80h`, it is assumed the program will call a function that issues `int 80h`, rather than issuing `int 80h` directly.
This convention is very convenient, and quite superior to the Microsoft(R) convention used by MS-DOS(R). Why? Because the UNIX(R) convention allows any program written in any language to access the kernel.
kernel:
int 80h ; Call kernel
ret
open:
push dword mode
push dword flags
push dword path
mov eax, 5
call kernel
add esp, byte 12
ret
This is a very clean and portable way of coding. If you need to port the code to a UNIX(R) system which uses a different interrupt, or a different way of passing parameters, all you need to change is the kernel procedure.
But assembly language programmers like to shave off cycles. The above example requires a `call/ret` combination. We can eliminate it by ``push``ing an extra dword:
open:
push dword mode
push dword flags
push dword path
mov eax, 5
push eax ; Or any other dword
int 80h
add esp, byte 16
open:
push dword mode
push dword flags
push dword path
mov eax, 5
push eax ; Or any other dword
int 80h
add esp, byte 16
The `5` that we have placed in `EAX` identifies the kernel function, in this case `open`.
Linux is a UNIX(R) like system. However, its kernel uses the same system-call convention of passing parameters in registers MS-DOS(R) does. As with the UNIX(R) convention, the function number is placed in `EAX`. The parameters, however, are not passed on the stack but in `EBX, ECX, EDX, ESI, EDI, EBP`:
open:
mov eax, 5
mov ebx, path
mov ecx, flags
mov edx, mode
int 80h
open:
mov eax, 5
mov ebx, path
mov ecx, flags
mov edx, mode
int 80h
This convention has a great disadvantage over the UNIX(R) way, at least as far as assembly language programming is concerned: Every time you make a kernel call you must `push` the registers, then `pop` them later. This makes your code bulkier and slower. Nevertheless, FreeBSD gives you a choice.
% brandelf -t Linux filename
If you are coding specifically for FreeBSD, you should always use the UNIX(R) convention: It is faster, you can store global variables in registers, you do not have to brand the executable, and you do not impose the installation of the Linux emulation package on the target system.