English Persian
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. تمامی حقوق محفوظ است.
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
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
0 STD NOHIDE { int nosys(void); } syscall nosys_args int
1 STD NOHIDE { void exit(int rval); } exit rexit_args void
2 STD POSIX { int fork(void); }
3 STD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
4 STD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
5 STD POSIX { int open(char *path, int flags, int mode); }
6 STD POSIX { int close(int fd); }
etc...
0 STD NOHIDE { int nosys(void); } syscall nosys_args int
1 STD NOHIDE { void exit(int rval); } exit rexit_args void
2 STD POSIX { int fork(void); }
3 STD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
4 STD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
5 STD POSIX { int open(char *path, int flags, int mode); }
6 STD POSIX { int close(int fd); }
etc...
%ifdef LINUX
%define SYS_execve 11
%else
%define SYS_execve 59
%endif
%ifdef LINUX
%define SYS_execve 11
%else
%define SYS_execve 59
%endif
sys.open:
sys.close:
[etc...]
int 80h
ret
sys.open:
sys.close:
[etc...]
int 80h
ret
This is the approach we will use throughout this chapter. We will name our include file [.filename]#system.inc#, and add to it whenever we deal with a new system call. این روشی است که ما در طی این فصل از آن استفاده می‌کنیم. پروندهٔ include خود را <filename>system.inc</filename> نام‌گذاری می‌کنیم، و هر زمان که در حال کار با یک فراخوان سامانهٔ جدید هستیم در آن اضافه می‌کنیم.
We can start our [.filename]#system.inc# by declaring the standard file descriptors: می‌توانیم <filename>system.inc</filename> خود را با اعلان توصیف‌گرهای پروندهٔ استاندارد آغاز کنیم:
%define stdin 0
%define stdout 1
%define stderr 2
%define stdin 0
%define stdout 1
%define stderr 2
%define SYS_nosys 0
%define SYS_exit 1
%define SYS_fork 2
%define SYS_read 3
%define SYS_write 4
; [etc...]
%define SYS_nosys 0
%define SYS_exit 1
%define SYS_fork 2
%define SYS_read 3
%define SYS_write 4
; [etc...]
section .text
align 4
access.the.bsd.kernel:
int 80h
ret
section .text
align 4
access.the.bsd.kernel:
int 80h
ret
%macro system 1
mov eax, %1
call access.the.bsd.kernel
%endmacro
%macro system 1
mov eax, %1
call access.the.bsd.kernel
%endmacro
Go ahead, enter it into your editor and save it as [.filename]#system.inc#. We will add more to it as we discuss more syscalls. ادامه دهید، آن را در ویرایش‌گر خود وارد کنید و به‌عنوان <filename>system.inc</filename> ذخیره کنید. در آینده که پیرامون فراخوان‌های سامانهٔ بیشتری بحث می‌کنیم، موارد بیشتری را به آن اضافه می‌کنیم.
1: %include 'system.inc'
2:
3: section .data
4: hello db 'Hello, World!', 0Ah
5: hbytes equ $-hello
6:
7: section .text
8: global _start
9: _start:
10: push dword hbytes
11: push dword hello
12: push dword stdout
13: sys.write
14:
15: push dword 0
16: sys.exit
1: %include 'system.inc'
2:
3: section .data
4: hello db 'Hello, World!', 0Ah
5: hbytes equ $-hello
6:
7: section .text
8: global _start
9: _start:
10: push dword hbytes
11: push dword hello
12: push dword stdout
13: sys.write
14:
15: push dword 0
16: sys.exit
Here is what it does: Line 1 includes the defines, the macros, and the code from [.filename]#system.inc#. آنچه که انجام می‌دهد بدین شرح است: خط 1 شامل تعریف‌ها (defines)، ماکروها، و کدهای <filename>system.inc</filename> است.
Lines 3-5 are the data: Line 3 starts the data section/segment. Line 4 contains the string "Hello, World!" followed by a new line (`0Ah`). Line 5 creates a constant that contains the length of the string from line 4 in bytes. خط 3 تا 5 شامل داده‌هاست: خط 3 بخش/تکهٔ داده‌ها را آغاز می‌کند. خط 4 شامل رشتهٔ "Hello, World!" و به‌دنبال آن خط جدیدِ (<constant>0Ah</constant>) است. خط 5 یک مقدار ثابت که شامل طول رشتهٔ خط چهارم در بایت‌هاست را ایجاد می‌کند.
Next, we ask the system to write the three bytes of the buffer, i.e., the two hexadecimal digits and the blank space, to [.filename]#stdout#. We then jump back to the beginning of the program and process the next byte. سپس، از سامانه درخواست نوشتن سه بایت از میان‌گیر را می‌کنیم، برای مثال، دو رقم شانزده‌شانزدهی و یک فضای خالی، برای <filename>stdout</filename>. سپس برگردید به ابتدای برنامه و بایت بعدی را پردازش کنید.
Can we improve this? Well, for one, it is a bit confusing because once we have converted a line of text, our input no longer starts at the beginning of the line. We can modify it to print a new line instead of a space after each `0A`: آیا می‌توانیم این مسئله را بهبود ببخشیم؟ خوب، به یک دلیل، کمی گیج‌کننده است زیرا همین‌که خطی از متن را تبدیل کردیم، ورودی ما دیگر از ابتدای خط شروع نمی‌شود. می‌توانیم آن را تغییر دهیم تا بعد از هر <constant>0A</constant>، به جای چاپ کردن یک فضا، یک خط جدید چاپ کند:
Once you have changed [.filename]#hex.asm# to reflect these changes, type: پس از آنکه <filename>hex.asm</filename> را تغییر دادید، برای انعکاس تغییرات، بنویسید: