الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كتابة برنامج لانشاء وتحرير الملفات النصية

مغلق
بدأه Xacker في 18 نوفمبر 2005 · 13 رد · 5,040 مشاهدة · في لغة Assembly لأنظمة 16, 32, 64 بت
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

يبدو ان موضوع فتح الملفات النصية والتعديل فيها وانشاؤها امر يطرح كثيرا في الكليات التي تدرس لغة الاسمبلي :)

لذا سنقوم في هذا الدرس بمناقشة كيفية كتابة تطبيق ببيئتي 16bit و 32bit يقوم بانشاء ملفات نصية / فتحها / التعديل فيها بالكتابة / الحفظ والاغلاق وارجو ان يغطي هذا الموضوع الحالية والتي لا بد وان تطرح في المستقبل حوله لجميع طلاب الكليات والمعاهد التقنية.

التطبيق ببيئة 16bit:

بما ان هذه البيئة تفرض بعض العوائق دعونا نستعرض اولا ماهية التعليمات والاوامر التي سنقوم باستخدامها وخصوصا المقاطعات وسنتناول في هذا الموضوع مقاطعة 21h -- (قد لا تعمل هذه المقاطعة بالشكل الصحيح على انظمة مثل XP -- النظام الذي اعمل عليه حاليا هو Windows 2003 Enterprise ويماثل العمل عليه العمل على 2k+XP اي ان المشاكل التي ستتعرضون اليها من المفترض ان اغطيها في المقال واي خلل خارجي ارجو طرحه لمناقشته).

ما هي المقاطعات؟

المقاطعات Interrupts يمكن النظر اليها على انها مجموعة من الوظائف والتي تجعل عملية البرمجة اسهل, فبدلا من ان نقوم بكتابة كود ليقوم بطباعة محرف ما على الشاشة يمكننا ان نقوم باستدعاء هذه المقاطعة لتنفيذ هذا الامر بدلا من منا!

تقسم المقاطعات الى قسمين, مقاطعات برمجية Software interrupts ومقاطعات صلبة Hardware interrupts فالاولى تختص بالتعامل مع القرص وبعض الاجهزة المعينة والاخيرة تختص بالتعامل مع اجهزة اخرى مثل البيوس وخلافه. ما يهمنا حاليا هو المقاطعات البرمجية وبالتحديد المقاطعة المشهورة 21h.

يتم استدعاء اي مقاطعة بتمرير عدد من البارامترات المعينة والتي تحدد الوظيفة المطلوبة من المقاطعة اجراؤها قبل استدعائها -- هذا النوع من تمرير البارامترات ملزم بشكل معين حيث يتم دفع هذه البارامترات وتخزينها في مسجلات الاغراض العامة مثل AX, BX, CX وقد يتم استخدام بعض المسجلات الاخرى مثل DX لتخزين قيم معينة فيها كالسلاسل النصية.. اخيرا يتم استدعاء المقاطعة بالشكل التالي:

int          NUM

حيث ياخذ الـ NUM قيما بين 0 - 255 (اي بالتمثيل الست عشري 00h - 0FFh) -- يجدر الاشارة هنا الى ان استدعاء المقاطعة يتم باستخدام الرقم بالتمثيل العشري لها اي لا يمكن استخدام النظام العشري في هذه الحالة والسبب واضح في البرمجة بشكل عام!

قد يتبادر الى الذهن ان هناك فقط 256 وظيفة (مقاطعة) يمكن استخدامها لكن هذا خطا, فكل مقاطعة تملك عددا من الخيارات التي بامكانها القيام بتنفيذها sub-function ويتم تحديد هذه الوظيفة الفرعية من خلال تخزين قيمة (رقم) الوظيفة في المسجل AH (حصرا) قبل القيام باستدعاء الوظيفة..

تملك كل مقاطعة عددا من الوظائف الفرعية يصل عددها الى 256 ايضا وبالتالي نرى اننا نملك 256 * 256 = 65536 وظيفة يمكننا استخدامها لتنفيذ الاعمال المطلوبة منا! لكن هل نحن بحاجة الى معرفة كل هذه الوظائف واستخداماتها؟ اعتقد ان هذا الامر ضرب من المستحيل.. ناهيك عن الجنون :D

يمكن الحصول على قائمة بكامل المقاطعات المتوفرة مع خياراتها من خلال الموقع التالي حيث تعد قائمة Ralf Brown اكبر واشمل قائمة للمقاطعات المتوفرة مع شرح استخدامها بالتفصيل شبه الممل:

http://www.cs.cmu.edu/~ralf/files.html

ماذا نحن بحاجة لمعرفته عن مقاطعة 21h؟

توفر لنا المقاطعة المذكورة امكانية فتح وتحرير الملفات بصورة سهلة جدا حيث تملك عددا من الخيارات او ما اسميناه الوظائف الفرعية الخاصة بالتعامل مع الملفات وهذه الوظائف هي:

- انشاء الملف: 3Ch

- فتح الملف: 3Dh

- الكتابة في الملف: 40h

- اغلاق الملف: 3Eh

- حذف الملف: 41h

سنقوم الان باخذ صورة اوضح عن استخدامات هذه الوظائف الفرعية ومناقشتها كل على حدة.

مقاطعة انشاء الملفات 213Ch:

تقوم هذه المقاطعة بانشاء الملف المطلوب في المجلد الحالي للبرنامج وتعيد قيمة مقبض الملف file handle في المسجل AX في حال نجاح التنفيذ وتكون القيمة المرتجعة في مسجل راية الحمل Carry Flag او اختصارا CF مساوية الصفر - او تعيد قيمة 1 في مسجل CF دليل حدوث خطا ما ويتم ارجاع رقم الخطا في المسجل AX (ويكون اما 3, 4, 5 ولكل منهم دلالة سنطلع عليها فيما بعد) -- بالتالي نرى انه من المهم تحديد فيما ان وجد خطا ما للتعامل معه حسب الضرورة ويمكن تطبيق هذا باستخدام تعليمة مثل JC (Jump if Carry) والتي يتم تنفيذها في حال كانت القيمة المخزنة في المسجل CF مساوية الواحد.

عندما يتم تنفيذ هذه الوظيفة بنجاح فانه في حال وجود ملف بنفس الاسم في المجلد الحالي للبرنامج فان حجم الملف يتم ارجاعه للصفر والغاء جميع البيانات فيه كما لو انك قمت بحذفه واعادة انشائه لذا يجب الانتباه هنا الى التحقق من وجود الملف في نفس المجلد او اتخاذ اسم جديد للملف للابقاء على الملف السابق دون المساس به. سنقوم بمناقشة معظم هذه الحالات فيما بعد.

- كيف نقوم باستخدام هذه الوظيفة؟

يتم اولا طلب الوظيفة بدفع القيمة 3Ch الخاصة بالوظيفة الى المسجل AH (كما اوضحنا سابقا) ومن ثم يتم دفع قيمة الى المسجل CX تحدد هذه القيمة خصائص الملف المراد انشائه فاما ان يكون للقراءة فقط او عادي او ملف نظام او مخفي .. الخ

فيما بعد يتم دفع اسم الملف الى المسجل DX ويتم طلب المقاطعة 21h بشكل عادي.

فيما يلي شكل طلب تنفيذ هذه الوظيفة من المقاطعة 21h:

mov     ah, 3Ch
;--------------------
; Bitfields for file attributes:
; Bit(s)	Description	(Table 01401)
; 2-0     create mode
; 000     normal
; 001   read-only
; 010   hidden
; 100   system
;--------------------
mov     cx, 0       ; 000000b
lea     dx, file_name
int     21h

يقوم الكود السابق بانشاء الملف الذي اسمه تم تخزينه في الدليل file_name والذي يتم تحميله الى المسجل DX باستخدام التعليمة LEA والتي هي اختصار لـ Load Effective Address والتي تقوم بتحميل العنوان الخاص بدليل ما في احد المسجلات حيث تقاس الازاحة اوتوماتيكيا ويتم تخزين العنوان RVA الخاص بذلك الدليل في المسجل المطلوب -- لا باس ان لم تكن تعرف ما معنى RVA فليس مطلوبا منك كبداية ان تعرف ماهيته وان اردت الاطلاع اكثر راجع الدروس المتقدمة الخاصة بامن التطبيقات.

بالنسبة لخصائص الملف فكما يبدو من الشكل السابق فانه يتم التحكم بالخصائص وفقا لموضع البت الذي يحمل القيمة 1 والذي يحدد الخاصة المطلوبة -- فنحن قمنا بحفظ القيمة 0 في المسجل CX وبالتالي نكون قد طلبنا انشاء ملف عادي لا يحمل اي خاصية بينما لو اردنا مثلا انشاء ملف للقراءة فقط امكننا هذا بدفع القيمة 1b الى المسجل CX حيث نلاحظ اننا قمنا بوضع القيمة 1 في البت (الخانة 0 -الاولى-) -- القيمة السابقة تمثل فعليا بالشكل 0000001 وتم اهمال الاصفار على اليسار لانها لا تؤثر على التنفيذ -- ايضا يرجى الانتباه الى اننا قمنا بوضع الدليل "b" على يمين البت اشارة الى ان هذه القيمة تمثل بالنظام الثنائي وكان بامكاننا وضعها 1h او حتى 1 (عشريا) لكن كي يتم التوضيح ولانه سيكون هناك اختلاف فيما يخص انشاء ملف يحمل خاصية القراءة فقط و ملف نظام ومخفي حيث ستكون القيمة 111b او 7h او 7.

مقاطعة فتح الملف 213Dh:

تقوم هذه الوظيفة بفتح ملف عن طريق اسم الملف الذي يؤخذ من المسجل DX حيث نقوم اولا بدفع رقم الوظيفة المطلوبة الى المسجل AH ومن ثم نقوم بتحديد الوضع الذي نريد فتح الملف به (للقراءة, الكتابة, كلاهما) بدفع قيمة معينة للمسجل AL ونقوم بحفظ اسم الملف في DX كم نفذنا سابقا - عند تنفيذ الوظيفة بالشكل الصحيح فانه يتم ارجاع مقبض الملف في المسجل AX وتكون قيمة CF مساوية للصفر وفي حال العكس يتم ارجاع رقم الخطا في AX وتحمل CF القيمة 1 -- امر اخر لا ادري ان كان صحيحا او انه بسبب عدم التوافقية الكاملة مع النظام المستخدم, تقوم هذه الوظيفة عند تنفيذ الملف بانشاء الملف ان لم يكن موجودا اصلا اي انها تقوم بعمل مشابه لوظيفة 3Ch وبالتالي قد يكون بالامكان الاستغناء عن السابقة ان كان هذا الامر هو نفسه على جميع الانظمة.. يكون الشكل الاخير للاستدعاء:

mov     ah, 3Dh
; Bitfields for access and sharing modes:
; Bit(s)	Description	(Table 01402)
; 2-0	access mode
; 000   read only
; 001   write only
; 010   read/write
mov     al, 10b    ; can also be '2' or '2h'
lea     dx, file_name
int     21h

الكتابة في الملفات باستخدام 2140h:

تقوم هذه الوظيفة بنقل عدد من البايتات (الاحرف) المحدد طولها في CX وتقوم بحفظها في ملف ما نقوم بتحديد المقبض الخاص به في المسجل BX بينما نقوم بتحديد السلسلة التي نريد كتابتها في الملف في المسجل DX واخيرا يتم تحديد رقم الوظيفة في AH - عند التنفيذ الصحيح: AX = عدد البايتات المكتوبة فعليا في الملف / CF = 0 -- عند حدوث اي خطا: AX = رقم الخطا (5, 6) / CF = 1

وفيما يلي شكل يمثل كيفية تنفيذ ذلك:

mov	ah, 40h
; can also be "mov    ax, 40h"
mov     bx, file_handle
mov     cx, string_len
lea     dx, buffer
int     21h

اغلاق الملف المفتوح بواسطة 213Eh:

تقوم هذه الوظيفة باغلاق ملف ما عن طريق وضع رقم الوظيفة في AH - مقبض الملف في BX - واستدعائها بواسطة المقاطعة 21h -- يمثل ذلك بالصورة التالية:

mov     ah, 3Eh
mov     bx, file_handle
int     21h

حذف ملف ما بواسطة 2141h:

تقوم هذه الوظيفة بحذف ملف موجود في نفس المجلد الحالي للبرنامج عن طريق وضع رقم الوظيفة في AH - حفظ اسم الملف في DX ومن ثم تنفيذ 21h -- يكون شكل التنفيذ كما يلي:

mov     ah, 41h
lea     dx, file_name
int     21h

قائمة بانواع الاخطاء اثناء التنفيذ:

 00h (0)   no error
 01h (1)   function number invalid
 02h (2)   file not found
 03h (3)   path not found
 04h (4)   too many open files (no handles available)
 05h (5)   access denied
 06h (6)   invalid handle
 07h (7)   memory control block destroyed
 08h (8)   insufficient memory
 09h (9)   memory block address invalid
 0Ah (10)  environment invalid (usually >32K in length)
 0Bh (11)  format invalid
 0Ch (12)  access code invalid
 0Dh (13)  data invalid
 0Eh (14)  reserved
 0Eh (14)  (PTS-DOS 6.51+, S/DOS 1.0+) fixup overflow
 0Fh (15)  invalid drive
 10h (16)  attempted to remove current directory
 11h (17)  not same device
 12h (18)  no more files

طبعا هذه قائمة صغيرة بالاخطاء التي قد تحصل لكنها تغطي ما قم تستخدمه من مقاطعات في الوقت الراهن وان اردت الاطلاع على كامل القائمة ما عليك سوى الاطلاع على ملف interrup.g في قائمة Ralf تحت وظيفة 2159h.

توسيع دائرة عمل البرنامج بواسطة عدد من الوظائف الاخرى:

كما نرى فان البرنامج السابق يقوم بكتابة بيانات معينة في الملف الذي قمنا بانشاؤه -- لكن ماذا لو اردنا ان نقوم بكتابة بيانات بانفسنا في ذلك الملف اي ان البيانات غير ثابتة ويقوم المستخدم بادخالها؟

في هذه الحالة نحن بحاجة الى استخدام الوظيفة 0Ah التي تقوم بانتظار المستخدم لادخال بيانات ويتم انهاؤها عند النقر على زر Enter (انهاؤها يعني انتقال التنفيذ الى الوظيفة التالية).

- كيف نقوم اذن باستخدام هذه الوظيفة؟

تستخدم وظيفة 0Ah لكتابة بيانات ادخلها المستخدم عن طريق وضع رقم الوظيفة في AH - تحديد عنوان الذاكرة او المخزن الذي سيتم الكتابة فيه بواسطة DX ومن ثم استدعاء الوظيفة بالشكل التالي:

mov     ah, 0Ah
lea     dx, buffer
int     21h

امر اخر -- البرنامج السابق يقوم بالكتابة في ملف قمنا بتحديد اسمه سابقا لكن ماذا لو اردنا القراءة من ذلك الملف, او تحديد فيما اذا كان موجودا سابقا لتجنب استبداله بملف اخر فارغ, كيف يكون السبيل الى ذلك؟

سنقوم لتنفيذ هذا الامر باستخدام 3 وظائف هي 4Eh التي تقوم بالبحث عن ملف ما على القرص ووظيفة 3Fh للقراءة من الملف ان وجد وعدم استبداله بملف اخر واخيرا سنتعرف على وظيفة 56h التي تقوم بتغيير اسم الملف.

- استخدام الوظيفة 4Eh للبحث عن الملف:

يتم استخدام هذه الوظيفة بوضع رقمها في المسجل AH - تحديد خصائص الملف المراد البحث عنه في CX - تحميل DX باسم الملف المراد البحث عنه ومن ثم استدعاؤها بالشكل التالي:

mov     ah, 4Eh
mov     cx, 0
lea     dx, file_name
int     21h

عند التنفيذ الصحيح للوظيفة تقوم بملئ منطقة DTA الخالية في FCB عند الازاحة 80h ببعض المعلومات حول الملف مثل مواصفاته, وقت الانشاء, تاريخ الانشاء, حجم الملف, اسم الملف.. لا باس ان لم تكن تعرف ما هي DTA و FCB لانه سيكون موضوع المقال القادم.

طبعا كما سبق فان التنفيذ الصحيح يعني ملئ CF بالقيمة 0 والعكس صحيح.

- استخدام الوظيفة 3F للقراءة من الملف:

يتم استخدام الوظيفة بوضع رقمها في AH - تحميل مقبض الملف في BX - عدد البايتات المراد قراءتها في CX - وعنوان المنطقة (المخزن) الذي سيتم فيه تخزين البيانات المقروءة في DX ومن ثم استدعاؤها بالشكل:

mov     ah, 3Fh
mov     bx, file_handle
mov     cx, 512
lea     dx, buffer
int     21h

في حال نجاح التنفيذ يتم تحميل عدد البايتات المقروءة في AX و صفر في CF وفي حال فشله.. :P

- استخدام الوظيفة 56h لتغيير اسم الملف:

تقوم هذه الوظيفة بتغيير اسم الملف عن طريق وضع رقم الوظيفة في AH - تحميل DX بالاسم الحالي للملف - تحميل DI بالاسم الجديد للملف وتنفيذها بالشكل:

mov     ah, 56h
lea	dx, old_name
lea     di, new_name
int     21h

الشكل الكامل لكود برنامج التعامل مع الملفات:

; Copyrighted (c) 2005 ArabTeam2000 - All rights reVersed :D
; w h a t  a r e  y o u  g o i n g  t o  d o  a b o u t  i t
;-----------------------------------------------------------
; This lame program does the following:
; 1- Takes the name of file to open/create
; 2- Searchs current directory for the file: 
; a) found: Asks the user to choose wheather to 
; rename, delete & create another, read & display the contents on screen.
; b) not found: creates the file and open it for write access
;-----------------------------------------------------------
;   I live on your money so be kind and send me some }:]
;-----------------------------------------------------------
.model  small
.code
        org     100h
start:
        jmp     main

; this program uses FCB techniques - explaination later on :p
name_skelton    label          byte
                max_len   db    55    ; avoids buffer overflow & arbitrary code execute - Qnix;)
                act_len   dw    ?
                file_name db    50 dup (?)
new_name_skel   label              byte
                new_max_len   db    55
                new_act_len   dw    ?
                new_file_name db    50 dup (?)
ext     db      '.txt', 0
ask     db      '(1) rename (2) delete & create (3) read & display', 13, 10, '$'
handle  dw      ?
in_buff db      250 dup (?)
file_buffer     label          byte
                maxl   db    255
                actl   dw    ?
                o_buff    db    250 dup (?)
op_err  db      'Error openning file', 0
re_err  db      'Error reading file', 0
ren_err db      'Error renaming file', 0
de_err  db      'Error deleting file', 0
cr_err  db      'Error creating file', 0
wr_err  db      'Error writing file', 0
cl_err  db      'Error closing file', 0

main    proc    near
        call    get_file              ; calls sub-routine get_file
        call    loc_file              ; calls sub-routine loc_file
        call    take_action           ; calls sub-routine take_action
        ret
main    endp

get_file    proc    near
; waits the user to enter the file name and stores it in file_name
        mov     ah, 0Ah
        lea     dx, name_skelton
        int     21h

; now because the file name needs extension we append the ext here
; using the act_len and principle of OFFSET
        mov     ax, act_len           ; al holds the length of entered name
        lea     bx, file_name         ; loads addr of 'file_name' block in bx
        add     bx, ax                ; locates the end of the entered name
        mov	si, word ptr [ext]    ; moves two bytes from 'ext' to si 
        mov     [bx], si              ; appends 1st two bytes '.t'
        mov     si, word ptr [ext]+2  ; moves last bytes from 'ext' to si
        mov     [bx]+2, si            ; appends last two bytes 'xt'

; by the end of this procedure we have 'file_name.txt' stored in memory :)
        ret                           ; return to main proc
get_file    endp

loc_file    proc    near
; search for the file in current directory
        mov     ah, 4Eh
        mov     cx, 0
        lea     dx, file_name
        int     21h
        jc      nFound
        mov     ax, 0
        ret
nFound:
        mov     ax, 1
        ret

; by the end of this proc we have either 0 or 1 in ax to determine the results
loc_file    endp

take_action proc    near
; option explicit :]]
        cmp     ax, 1
        je      file_not_found
file_found:
        mov     ah, 09h               ; service 09 (display characters)
        lea     dx, ask
        int     21

        mov     ah, 0                 ; service 00 (read a character)
        int     16h                   ; execute 16h interrupt
        cmp     al, 31h
        je      rename
        cmp     al, 32h
        je      delete
open:
        mov     ax, 3D00h             ; service 3D (open file for read-only)
        lea     dx, file_name
        int     21h
        jc      open_err
        mov     handle, ax
read:
        mov     ah, 3Fh
        mov     bx, handle
        mov     cx, 250
        lea     dx, o_buff
        int     21h
        jc      read_err
display:
        mov     ah, 09h
        lea     dx, o_buff
        int     21h

        jmp     close
rename:
        mov     ah, 0Ah
        lea     dx, new_name_skel
        int     21h
        mov     ax, new_act_len
        lea     bx, new_file_name
        add     bx, ax
        mov	si, word ptr [ext]
        mov     [bx], si
        mov     si, word ptr [ext]+2
        mov     [bx]+2, si

        mov     ah, 56h
        lea     dx, file_name
        lea     di, new_file_name
        int     21h
        jc      rename_err

        jmp     exit
delete:
        mov     ah, 41h
        lea     dx, file_name
        int     21h
        jc      delete_err

create:
        mov     ah, 3Ch
        mov     cx, 0
        lea     dx, file_name
        int     21h
        jc      create_err
        mov     handle, ax

recieve:
        mov     ah, 0Ah
        lea     dx, in_buff
        int     21

write:
        mov     ah, 40h
        mov     bx, handle
        mov     cx, actl
        lea     dx, o_buff
        int     21h
        jc      write_err

close:
        mov     ah, 3Eh
        mov     bx, handle
        int     21h
        jc      close_err

        jmp     exit

open_err:
        mov     ah, 09h
        lea     dx, op_err
        int     21h

        jmp     exit
read_err:
        mov     ah, 09h
        lea     dx, re_err
        int     21h

        jmp     exit
rename_err:
        mov     ah, 09h
        lea     dx, ren_err
        int     21h

        jmp     exit
delete_err:
        mov     ah, 09h
        lea     dx, de_err
        int     21h

        jmp     exit
create_err:
        mov     ah, 09h
        lea     dx, cr_err
        int     21h

        jmp     exit
write_err:
        mov     ah, 09h
        lea     dx, wr_err
        int     21h

        jmp     exit
close_err:
        mov     ah, 09h
        lea     dx, cl_err
        int     21h

        jmp     exit
file_not_found:
        jmp     create
exit:
        ret

take_action endp

end     start

رغم ان الكو السابق من المفترض ان يكون كاملا وان يعمل دون اخطاء لكن الخطا وارد خصوصا اني غير قادر على تشغيل الملف التنفيذي واختباره لاني اعمل على نظام لا يدعم جميع المقاطعات, اعتقد ان الخطا سيكون في حجم الملف ومحدودية احجام ملفات com والله اعلم -- لكن المهم هو فهم اليات الاستخدام والعمل على تطوير الكود السابق لتغطية كافة الاخطاء وادخال اجرائيات فحص جديدة او اجرائيات تزيد من فعالية البرنامج او حتى التخفيف من التعليمات المستخدمة بوضع الوظائف المتكررة في اجرائيات مستقلة واستدعاؤها عند الحاجة -- لا احتاج للقول اني توقفت عن كتابة تطبيقات 16بت منذ زمن طويل لذا يعتبر كتابة تطبيق (وان احتوى اخطاء :P) يستخدم مسجلات 16بت ومقاطعة 21h دون ان افقد صوابي انجاز كبير لي p;

- ملاحظة اخيرة بخصوص اختبار الكود على بقية الانظمة مثل 9x - يفضل ان تقوم بتدريب نفسك على كتابة البرنامج بعد فهم الدرس ومحاولة ادخال افكار جديدة ومن ثم اختباره -- للاسف مستخدمي Emu8086 احمل اخبار سيئة لكم وهي انه لا يدعم كافة المقاطعات الواردة في هذا المقال وبالتالي "انسوه :P" -- يمكن استخدام masm16 لكن الملف الناتج في النهاية .exe وسيكون بحجم اكبر من المطلوب بسبب الـ 512bit زيادة :P بالتالي سنقوم بتحويله الى ملف .com باستخدام برنامج EXE2BIN ويمكن ايجاده في المنتدى او من خلال هذا الموقع -- استخدامه سهل للغاية حتى اخي سامي الصغير بيعرف كيف يشتغل على masm16 و exe2bin :P

http://www.ibiblio.org/pub/micro/pc-stuff/...bin/exe2bin.exe

ماذا بشان التطبيق ببيئة 32bit؟

بعد ان انتهيت من كتابة المقال وجدت بانه سيجعل القارئ يهرب من الصفحة الاولى :P لذا سنؤجل نقاشنا حول كتابة التطبيق السابق ببيئة 32بت الى الدرس القادم - يليه فهم كتلة الـ FCB - ومن ثم ننتقل الى التعامل مع الشاشة والتوسع في استقبال المحارف من الكيبورد... متمنيا ان انتهي من 16بت بسرعة D;

اسئلة؟

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#2

ما اعرف شيء عن الاسمبلي .. لكن اعجبني شرحك عن "المقاطعات" .. اول مرة افهمها .. وانفتحت نفسي للاسمبلي ..سبق لي المحاولة لكن ...

طبعا لن اطبق لاني ضعيف جدا بالاسمبلي .. لكن اقرأ شرحك النظري فهو مفيد جدا . . . هذا اللي عندي . :)

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#3

بيكفي انك تحاول يا الشمري -- اي معلومة تكتسبها ولو بعد ان تخطا 10 مرات هو انجاز !

بالتوفيق (وفينك من زمان يا رجال تجي تشاركنا هون -- ترا كتابة الالعاب بالاسمبلي متعة :P)

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#4

الموضوع جميل و الشرح أجمل شكراً لك Xacker

الحياة كلها وقفة عز فقط

------------------------------------------

المجتمع معرفة و المعرفة قوة

#5

مقال رائع يا xacker

بصراحة لقد فهمت الاوامر الفرعية للـ interrupt 21h وكيفية استخدامها لكن البرنامج الاخير طويل ولم استطع فهمه ككتلة واحدة...

ما استطعت فهمه هو ان هناك كود لجعل المستخدم يدخل اسم البرنامج وكود اخر لاضافة الامتداد .txt ووو...لكن ربما لو كان

البرنامج اصغر لكن افضل...

عموما حاولت عمل هذا البرنامج او الكود ان صح التعبير...اقتبست بعض اجزائه من البرنامج الطويل...عمله ان يقوم بانشاء ملف اسمه ali.txt ثم يقوم بفتحه ...ومن ثم يسمح لك بكتابة ما تريد فيه...وفي النهاية اغلاقه...

;this program is under the GPL license

.model small
.code

org     100h

start:
jmp     main
file_name   db  'ali.txt',0

main    proc    near

;creation
mov     ah,3ch
mov     cx,0
lea     dx,file_name
int     21

;opening
mov     ah,3dh
mov     al,2
lea     dx,file_name
int     21h

;writing
mov     ah,0ah
lea     dx,file_name
int     21h

;closing
mov     ah,3eh
mov     bx,file_handle
int     21h

ret
main    endp
end     start

لاحظ ان file_handle غير معرّف...

لم استطع تنفيذه لانه ظهر لي error...وهو نفس ال error ألذي ظهر حينما حاولت تنفيذ برنامجك...

19_11_05_10_20_03_1132424403error.JPG

لدي اسئلة حول البرنامج الذي قمت انا بكتابته...

1- هل يمكن استبدال

file_name   db  'ali.txt',0
بـ
file_name   db  'ali.txt$'

2-اليس من المفروض ان ينتهي البرنامج(سواء الذي كتبته انا ام اذي كتبته انت)

بـ INT 21h

AH=4Ch

المسؤولة عن اعادة التوجيه الى الدوس؟

3- من اين احصل على الـ file_handle اللازمة لغلاق الملف؟

وشكرا جزيلا

تم تعديل هذه المشاركة بواسطة allko في 19 نوفمبر 2005 في 21:16

#6

1- الا تعتقد ان التطبيق خاص بـ 16بت يعني masm16 :)

2- نعم يمكن.

3- هممممم - لم اضطر كثيرا لاستخدامها لكن استخدامها افضل من عدمه -- تابع

4- من خلال وظيفة فتح الملف - القيمة المرتجعة تكون المقبض - احفظها في file_handle مثلا وتابع (لازم يكون بحجم 2 بايت)

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#7

بخصوص ال file handle ...

اقتباس
عند تنفيذ الوظيفة بالشكل الصحيح فانه يتم ارجاع مقبض الملف في المسجل AX

وتكون قيمة CF مساوية للصفر وفي حال العكس يتم ارجاع رقم الخطا في AX

وتحمل CF القيمة 1

قراتها لكن ربما لم اركز جيدا...يبدوا انني يجب ان ارفع مستوى تركيزي عند قراءة مقالاتك القادمة :rolleyes:

اقتباس
الا تعتقد ان التطبيق خاص بـ 16بت يعني masm16 "

نعم اعرف...ولذلك جربت عمله بـ masm16 & masm 32 وفي كلا الحالتين ظهر لي error

ففضلت ان ارفق صورة الـ error الخاص بـ 32 ...على كل هذه صورة للerror في حالة 16

لـ"بريمجي" وبرنامجك...

19_11_05_02_28_47_1132439327error_.JPG

وهذه لبرنامجك

19_11_05_02_29_30_1132439370error3.JPG

سلام

#8

:P بالنسبة لبرنامجي اعتقد اننا تجاوزنا الطول المسموح لبرامج COM :P معلش امركم لله -- افهموا الدرس بدون تطبيق :) على الاقل اكتبوا تطبيقات تدريبية متل ما عمل علي باستخدام الوظائف المتنوعة اللي تم مناقشتها..

بالنسبة للمشكلة الاولى لا ارى لها حلا من هنا .. يمكن لازم انتقل للغرفة التانية.. دقيقة.......... (وبعد دقيقة).. ما زلت لا ارى حلا حتى من الغرفة التانية :P احيانا يحدث هذا معي لكن المسار يكون طويل وبفراغات وعند الانتقال الى الجذر الرئيسي للسواقة يختفي الخطا.. تاكد ان الملف باللاحقة .asm وليس .txt

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#9

:rolleyes:

بالطبع فان الامتداد هوasm وليس txt :rolleyes:

عالعموم عحاول اتاكد مرة تانية بس مش هلئيت...بعد يوم التلاتاء لانو عليا امتحان ++C

سلام

تم تعديل هذه المشاركة بواسطة allko في 21 نوفمبر 2005 في 01:27

#10

امتحان C للالكترونيات... نيالك :D

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#11

نيالي...مممم...افهم من كلامك انك بتعتبرها مادة ثانوية بالنسبة لتخصص هندسة الاتصالات؟ :rolleyes:

وبالتالي من حسن حظي انهم بدرسونا اياها مع انها بتلزمنيش كتير؟ :rolleyes:

(على فكرة الاتصالات بتشبه الالكترونيات)

انا بوافقك الراي بس اعتقد انو الا ما تلزمنا بيوم من الايام...

بخصوص الكود فعحاول اشوف المشكلة بس بعد الامتحان( عالـ 11)

سلام

#12

استخدمت RadASM وقمت بالـ assembling بنجاح لكن ظهر هذا الخطا اثناء الـ linking

22_11_05_10_19_17_1132683557error3.GIF

#13

حاول ان تقوم بكتابة برنامجك باجرائيات صغيرة في البداية وتابع زيادة الحجم وتاكد بانك لن تستطيع الاضافة اكثر من 64k ..

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#14

أخي جزاك الله خيرا

ولكن أردت أن أسأل عن كيفية القيام بنسخ الملف ونقله

وجزاك الله خيرا

هذا الموضوع مغلق.

مواضيع مشابهة