آموزش اسمبلی - Assembly

وضعیت
موضوع بسته شده است.

saalek110

Well-Known Member
برنامه گرفتن ساعت كامپيوتر:
برنامه زير اين طوري نشان مي دهد:
کد:
1133-3200-11
كه يعني ساعت 11 و 33 دقيقه و 32 ثانيه است. و 11 ساعت هم از نيمه شب گذشته.
با تغيير ساعت كامپيوتر خود ببينيد من درست گفتم يا نه.
در كد قسمتي help همان اموليتوره كه من نقل كردم. اصل برنامه هم اين كده:
mov ah,2
int 1ah
مي توانيد اين دو خط كد را برداريد و باقي اش را خودتان بنويسيد. البته با وقفه هاي ديگر هم فكر كنم ساعت را بشه نمايش داد. خروجي را هم در كدها مي بينيد كه بايد در آن رجيسترها دنبالش بگرديد.

بقيه برنامه جز اين دو خط كد:
با احضار زير برنامه bl_print چاپ رجيستره تا ببينيم ساعت چنده. شايد من جاهايي غلط نوشتم . خودتان اصلاح كنيد. . نمي دانم چرا dl تغيير نمي كنه.شايد هم دليلي نداره كه تغيير كنه. چون ثانيه در dh بود و تمام شد ديگه.اين برنامه براي تنوع بود.
اين تكه هم كه براي چاپ منهاست. براي احتياط رجيستراش را پوش كردم.
push dx
push ax
mov ah,2
mov dl,'-'
int 21h
pop ax
pop dx

کد:
.model small
.stack
.data
.code
asli proc
;---------------------------
;INT 1Ah / AH = 00h - get system time.

;return:

;CX:DX = number of clock ticks since midnight.
;AL = midnight counter, advanced each time midnight passes.

;Notes:
;There are approximately 18.20648 clock ticks per second,
;and 1800B0h per 24 hours.
;AL is not set by emulator yet!
;----------------------
mov ah,2
int 1ah

mov bl,ch
call bl_print
mov bl,cl
call bl_print
;------
push dx
push ax
mov ah,2
mov dl,'-'
int 21h
pop ax
pop dx
;------
mov bl,dh
call bl_print
mov bl,dl
call bl_print
;------
push dx
push ax
mov ah,2
mov dl,'-'
int 21h
pop ax
pop dx
;------
mov bl,al
call bl_print

;---------------------------
mov ax,4c00h ; return to dos DOS
int 21h

asli endp
; ============ sub bl_print ===========
bl_print PROC NEAR
push ax
push bx
push cx
push dx
;----------part 1
mov ah,2h
mov dl,bl 

mov cl,04h
shr dl,cl

add dl,30h

cmp dl,3ah
jl lable1

add dl,07h

lable1:
int 21h

; -----------part 2

mov dl,bl
and dl,0fh

add dl,30h

cmp dl,3ah
jl lable2

add dl,07h

lable2:
int 21h
;------------
pop dx
pop cx
pop bx
pop ax

ret ; return to where it was called
bl_print ENDP
;===================================

     end asli
براي تفريح بيشتر من حلقه كردم اول و آخر برنامه را.
البته براي خروج هم چيزي در نظر نگرفتم. اين تكه را انداختم آخر برنامه:
;============
mov dh,0 ;DH = row.
mov dl,0 ;DL = column.
mov ah,2 ;service
int 10h
jmp lablexxx
;===========
كه كرزر را مي آورد اول صفحه. و بعد جامپ مي كند به اول برنامه در lablexxx .
کد:
.model small
.stack
.data
.code
asli proc
;---------------------------
;INT 1Ah / AH = 00h - get system time.

;return:

;CX:DX = number of clock ticks since midnight.
;AL = midnight counter, advanced each time midnight passes.

;Notes:
;There are approximately 18.20648 clock ticks per second,
;and 1800B0h per 24 hours.
;AL is not set by emulator yet!
;----------------------
lablexxx:
mov ah,2
int 1ah

mov bl,ch
call bl_print
mov bl,cl
call bl_print
;------
push dx
push ax
mov ah,2
mov dl,'-'
int 21h
pop ax
pop dx
;------
mov bl,dh
call bl_print
mov bl,dl
call bl_print
;------
push dx
push ax
mov ah,2
mov dl,'-'
int 21h
pop ax
pop dx
;------
mov bl,al
call bl_print
;============
mov dh,0  ;DH = row.
mov dl,0  ;DL = column.
mov ah,2  ;service
int 10h
jmp lablexxx
;===========
;---------------------------
mov ax,4c00h ; return to dos DOS
int 21h

asli endp
; ============ sub bl_print ===========
bl_print PROC NEAR
push ax
push bx
push cx
push dx
;----------part 1
mov ah,2h
mov dl,bl 

mov cl,04h
shr dl,cl

add dl,30h

cmp dl,3ah
jl lable1

add dl,07h

lable1:
int 21h

; -----------part 2

mov dl,bl
and dl,0fh

add dl,30h

cmp dl,3ah
jl lable2

add dl,07h

lable2:
int 21h
;------------
pop dx
pop cx
pop bx
pop ax

ret ; return to where it was called
bl_print ENDP
;===================================

     end asli

حالا شد شبيه ساعت كامپيوتري. اگر دكمه full screen را در بالاي پنجره داسي بزنيد حركت سريع كرزر را بهتر مي بينيد.
 
آخرین ویرایش:

saalek110

Well-Known Member
من از dh و dl استفاده كردم. و اين دو در دو حلقه خارجي و داخلي در حال افزايش هستند. و در cmp ها به راحتي از ين دو استفاده كردم. شما هم نياز داريد تا 2 رجيستر را در حلقه بيروني و حلقه دروني افزايش دهيد تا در عمق حلقه اين دو ابزار شما باشد. برنامه اي كه نستا براي رسم پيكسل ها نوشت هم ((حلقه اي تو در تو با cx و dx)) بود. در عمق حلقه نستا هم دو ابزار در اختيارش بود. ولي حلقه ((تو در تو فقط با cx )) اشكالش اينه كه در عمق حلقه ما به cx بيروني دسترسي نداريم. چون با push و pop روي حلقه داخلي پل زده ايم.
پس نمي توانيم در عمق حلقه بفهميم كه الان در كدام رديف هستيم. مگر رجيستري را در حلقه بيروني افزايش دهيد تا در عمق حلقه از آن استفاده كنيد. اگر نخواهيد اين كار را بكنيد بايد برنامه را 3 قسمت كنيد. قسمتي كه رديف اول را مي كشد . برنامه اي كه وسط را مي كشد و برنامه اي كه رديف آخر ستاره ها را رسم مي كند.
شما با برنامه ((اينتر كننده)) بايستي رجيستري را هم افزايش بدهيد كه بدانيد چند بار اينتر كرده ايد.
البته اگر منظور شما را درست فهميده باشم.
= = = = = = = = = ==
اما راجع به push و pop ها:
ببينيد ما گاهي از مثلا dl در 10 جاي برنامه مي خواهيم استفاده كنيم. با اين push و pop ها ما برنامه را پارتيشن بندي مي كنيم. برنامه زير را ببينيد:
Mov ah,2

Mov dl,33

Int 21h

كه كاركتر مربوط به عدد 33 را چاپ مي كند. اگر وسطش يك خطي باشد مثل mov dl,54 يعني اين طوري:

Mov ah,2
Mov dl,33

Mov dl,54

Int 21h

خوب معلومه كه 54 را چاپ مي كند نه 33 را. حالا من دو طرف 54 مي ايم push و pop مي گذارم:
Mov ah,2
Mov dl,33

Push dx
Mov dl,54
Pop dx

Int 21h
حالا ديگه همان 33 چاپ ميشه نه 54 . چون من پل زده ام روي 54.
منظورم از پل اينه كه قبل دستور 54 مي آيم يك نسخه از dx (شامل dl ) را در پشته كپي مي گيرم و بعد خط 54 مي آيم از آن كپي دوباره dx را ترميم مي كنم.
من اينجا خلاصه كردم و گفتم چاپ 33 و 54 . مي دانيد كه اولا ما دو مبناي عدد دادن داريم 16 و 10 كه اگر به 16 مي خواهيد بدهيد بايد بعد عدد حرف اچ را بگذاريد و ثانيا از جدول اسكي بايد نگاه كنيد كه وقفه با ديدن 33 و 54 چه كاراكتري را چاپ مي كند.
= = == = = = =
تمام زيربرنامه ها بايد رجيسترهايي را كه دستكاري مي كنند را push و pop كنند. مگر اين كه با يك رجيستر بخواهند خروجي بفرستند به برنامه اصلي كه او را صدا كرده. در اين مورد هم فقط آن رجيستر را باز مي گذاريم و بقيه را push و pop مي كنيم.

نكته مهم: آدرس برگشت زيربرنامه به برنامه اصلي ،يعني شماره خط آن خط كه بلافاصله بعد خطي قرار دارد كه دستور call داخلشه ، در پشته نگهداري ميشه. پس قبل رسيدن به دستور ret يعني بازگشت به برنامه اصلي بايد پشته را خالي كنيد.

براي راحتي اين طور مي شود گفت كه داخل هر زيربرنامه (يا برنامه اصلي) هر چيزي را كه push كرده ايد ، داخل همان زيربرنامه pop كنيد.
اين طوري استفاده شما از پشته با استفاده خود cpu از پشته تداخل نخواهد كرد
 
آخرین ویرایش:

saalek110

Well-Known Member
در صفحات 4 و 5 و 6 تاپيك داشتيم از يك سايت كه در 7 صفحه آموزش داده بود تمرين مي كرديم و صفحه 5 آن سايت را نگفتيم.
آدرس سايت:
http://burks.brighton.ac.uk/burks/language/asm/asmtut/asm1.htm

آدرس صفحه 5 آن:
http://burks.brighton.ac.uk/burks/language/asm/asmtut/asm6.htm

= = = = = = = = = = = = =
حالا كه سرمان خلوت شد كمي ، خوبه كه اونم بگيم. از طرفي شايد بشه با فايل خواني كارهاي جالبي كرد.
= = = = = == = = = = = =
چند برنامه در اين سايت است كه كد اولي را در زير مي آورم و با عكسي كه نتيجه اجراي آن است. در عكس فايل را با نت پد مي بينيد و مي بينيد كه نتيجه اجراي برنامه هم دقيقا همان است.
يادتان نرود قبل اجراي اين برنامه فايل تكستي با نام test در درايو سي بسازيد. يك بار هم بي فايل اجرا كنيد تا خطا را دريافت كنيد.


a1.jpg

کد:
.model small
.stack
.code

mov ax,@data ; base address of data segment
mov ds,ax ; put this in ds

mov dx,OFFSET FileName ; put address of filename in dx
mov al,2 ; access mode - read and write
mov ah,3Dh ; function 3Dh -open a file
int 21h ; call DOS service

mov Handle,ax ; save file handle for later
jc ErrorOpening ; jump if carry flag set - error!

mov dx,offset Buffer ; address of buffer in dx
mov bx,Handle ; handle in bx
mov cx,100 ; amount of bytes to be read
mov ah,3Fh ; function 3Fh - read from file
int 21h ; call dos service

jc ErrorReading ; jump if carry flag set - error!

mov bx,Handle ; put file handle in bx
mov ah,3Eh ; function 3Eh - close a file
int 21h ; call DOS service

mov cx,100 ; length of string
mov si,OFFSET Buffer ; DS:SI - address of string
xor bh,bh ; video page - 0
mov ah,0Eh ; function 0Eh - write character

NextChar:

lodsb ; AL = next character in string
int 10h ; call BIOS service
loop NextChar

mov ax,4C00h ; terminate program
int 21h

ErrorOpening:

mov dx,offset OpenError ; display an error
mov ah,09h ; using function 09h
int 21h ; call DOS service
mov ax,4C01h ; end program with an errorlevel =1
int 21h

ErrorReading:
mov dx,offset ReadError ; display an error
mov ah,09h ; using function 09h
int 21h ; call DOS service
mov ax,4C02h ; end program with an errorlevel =2
int 21h

.data
Handle DW ? ; to store file handle
FileName DB "C:\test.txt",0 ; file to be opened
OpenError DB "An error has occured(opening)!$"
ReadError DB "An error has occured(reading)!$"
Buffer DB 100 dup (?) ; buffer to store data

END

خيلي برنامه جالبي است. و علاوه بر خواندن فايل نكات ديگري هم دارد. يكي از نكاتش اينه كه 3 بار دستور خروج در آن بكار رفته اولي اين است:
mov ax,4C00h ; terminate program
int 21h

كه يك دستور خروج ساده است.
و دومي و سومي:
mov ax,4C01h ; end program with an errorlevel =1
int 21h
= = = = = =
mov ax,4C02h ; end program with an errorlevel =2
int 21h
مي بينيد كه 4c00 نيست و اعداد يك و دو در آن هست. يعني دارد به سيستم خطا را هم اعلام مي كند. البته من نمي دونم سيستم الان هم براش مهم است اين خطا ها يا فقط قديم در زمان dos مهم بوده. كلا من بحثي فعلا برايش ندارم.

حالا اين چند خروجي داشتن از اين لحاظ براي من جالب بود كه :
در برنامه مي بينيد كه برنامه در دستور خروج اول كارش تمام شده و در دستور خروج پايان مي يابد. اين طوري كدهاي بعدي كه كارشان چاپ پيغام خطا است در دسترس نيست و نمي خواهد جامپ كنيم از رويش و خيلي كار راحت تره.

اما برويم انتهاي برنامه راتوضيح بدهيم. يعني اينجا را:
.data
Handle DW ? ; to store file handle
FileName DB "C:\test.txt",0 ; file to be opened
OpenError DB "An error has occured(opening)!$"
ReadError DB "An error has occured(reading)!$"
Buffer DB 100 dup (?) ; buffer to store data

قسمت داده است اين قسمت و قبلا هم باهاش آشنا بوديد.
اولي هندل است. كه دو بايتي يعني يك كلمه است و مقدار اوليه بهش داده نشده و بعدا هندل درونش ريخته مي شود كه در قسمت فايل خواني در پايين شرح مي دهيم.
دومي يك رشته است كه مي دانيد رشته هاي كاراكتري را از نوع بايت انتخاب مي كنند . و در اينجا هم از نوع بايت انتخاب شده. كه مسير فايل درونش ريخته شده.
سومي و چهارمي هم كه پيغامهاي خطا است و بحثي ندارد.
و آخري هم كه نام متغير را ((بافر)) گذاشته و باز از نوع بايت است و 100 بايت رزرو كرده. و باز مقدار اوليه نداده و علامت سئوال گذاشته.

= = = = == == ==
حالا برويم از اول فايل توضيح بدهيم:

دو خط اول كه تنظيم قطعه داده است و به كرات استفاده شده و توضيح نياز ندارد. يعني اين قسمت:
mov ax,@data ; base address of data segment
mov ds,ax ; put this in ds
قسمت بعدي يعني اين قسمت:
mov dx,OFFSET FileName ; put address of filename in dx
mov al,2 ; access mode - read and write
mov ah,3Dh ; function 3Dh -open a file
int 21h ; call DOS service

قسمتي است كه فايل را باز مي كند. يعني open كننده است. كلمه open را براي اين آوردم چون كه اگر كسي با زبانهاي ديگر كار كرده باشه سريع مي فهمد كدام قسمت است. كلا فايل خواني در اكثر زبانها يكسان است.

در زير ورودي و خروجي سرويس باز كننده فايل كه يكي از سرويس هاي وقفه 21 است را با هم مي بينيم:
کد:
INPUT:

AH = 3Dh
AL = bits 0-2 Access mode
000 = read only
001 = write only
010 = read/write
bits 4-6 Sharing mode (DOS 3+)
000 = compatibility mode
001 = deny all
010 = deny write
011 = deny read
100 = deny none
DS:DX = segment:offset of ASCIIZ pathname

OUTPUT:

CF = 0 function is succesful
AX = handle
CF = 1 error has occured
AX = error code
01h missing file sharing software
02h file not found
03h path not found or file does not exist
04h no handle available
05h access denied
0Ch access mode not permitted

توضيح:
اول شماره سرويس را در ah قرار مي دهيم كه 3d است.
ميشه شماره سرويس را هم جزو ورودي ها دانست البته.
بعد al را تنظيم مي كنيم. مي دانيد كه al داراي 8 بيت است.
3 بيت اول براي نوع دسترسي است(بيت ها را از سمت راست مي خوانند) كه شماره هاي صفر و يك و دو براي ((فقط خواندن)) ((فقط نوشتن)) و ((خواندن و نوشتن)) است. در برنامه ما در al 2 گذاشته ايم يعني هم خواندن و هم نوشتن.

بيتهاي شماره 4 تا 6 درون al براي Sharing mode است كه من فعلا نمي دانم چيه.
مي دانيد كه بيت اول 1 است و بعدي 2 و بعدي 4 و بعدي 8 . پس بيتهاي صفر تا 7 را اينطوري برويد بالا. مثلا اگر بيت اول روشن باشه و آخري ميشه 1 بعلاوه 128 كه ميشه 129 . البته در مبناي 10 است اين عدد.
براي مبناي 16 مي توانيد 4 بيت 4 بيت در نظر بگيريد.
در مورد 129 . در بيتهاي 0 تا 3 داريم ((يك –صفر- صفر-صفر))
و در بيتهاي 4 تا 7 داريم (( صفر-صفر – صفر – يك)) كه اين 4 بيت را باز اين طوري بخوانيد ((يك – دو – چهار – هشت)) پس ما 8 داريم در 4 بيت دوم و يك داريم در 4 بيت اول كه ميشه 81 در مبناي 16.

از ورودي هاي ديگر مسير فايل است كه بايد روي متغيري كه حاوي آن است قبل اجراي سرويس تنظيم باشه. درست مثل چاپ رشته اي در قطعه داده كه اول روي آن متغير رشته اي تنظيم مي كرديم اين كار انجام شده. (مثل چاپ همين پيغام هاي خطا. ولي اينجا چاپي صورت نمي گيرد بلكه رشته توسط سرويس دريافت مي شود.كه مسير فايل است.)
 
آخرین ویرایش:

saalek110

Well-Known Member
ادامه پست قبل:

حالا خروجي ها:
دو حالت دارد. يكي اينكه كار موفقيت آميز بوده . يعني فايل باز شده كه هندل در ax قرار مي گيرد. حالا مي گيم هندل چيه.
در حالت موفقيت آميز فلاگ cf صفر است.

حالت بعدي شكست در باز كردن فايل است كه فلاگ cf يك مي شود و كد خطا در ax قرار مي گيرد.
حالا اينكه هر كد چه معني ئي دارد اينهاست:
01h missing file sharing software
02h file not found
03h path not found or file does not exist
04h no handle available
05h access denied
0Ch access mode not permitted
كه خودتان ترجمه كنيد. اطلاعات من در اين مورد بيشتر از شما نيست.

اما در اينجا كه بالا گفته:
DS:DX = segment:eek:ffset of ASCIIZ pathname
يعني چه؟
اين ASCIIZ را مي گويم يعني چه؟
جواب: در كدهاي نمونه برنامه ، در قسمت تعريف متغيرها در قسمت داده ها ، 3 متغير رشته اي تعريف شده. يعني اينها:
FileName DB "C:\test.txt",0 ; file to be opened
OpenError DB "An error has occured(opening)!$"
ReadError DB "An error has occured(reading)!$"

مي بينيد كه دو تاي آخري كه براي چاپ يك پيغام است با علامت دلار پايان يافته. و قبلا هم من گفتم كه مواظب باشيد در پايان رشته هاي براي چاپ اين علامت دلار را يادتان نرود چون ((نشانه پايان رشته)) است و اگر نباشه همين طوري رشته به خواندن ادامه داده ميشه تا بطور اتفاقي يك دلار پيدا بشه و بياستد.
ولي 3 خط كد بالا ، اولي كه مسير فايل است با دلار خاتمه نيافته بلكه با ((صفر )) خاتمه پيدا كرده. به اين ASCIIZ مي گويند. كه يك صفر تهش داره. صفر كه مي دونيد ميشه zero .
و اون يكي اسكي (ASCII ) بدون z بود و با دلار خاتمه مي يابد.

حالا برسيم به هندل:
هندل خروجي سرويسه كه در ax ريخته مي شود و در خط زير:
mov Handle,ax ; save file handle for later

درون متغير ريخته ميشود. متغير هم word گرفته شده تا اندازه ax باشه.
در سايت گفته براي نگهداري آن ميشه از رجيستر هم استفاده بشه ولي اين جوري يكي همش بايد يادمان باشه كه هندل توي اونه و ديگري اين كه اون رجيستر اشغال مي مونه و نميشه ازش براي كارهاي ديگه استفاده كرد.

حالا هندل چيه؟
ببينيد وقتي تابع open كه در اين برنامه اسمبلي يك سرويس از يك وقفه است تابعي را باز مي كند ، چيزي مثل يك پرچم ايجاد مي كنه يا مثل يك ويزاي عبور كه تمام توابعي كه بخواهند از اون فايل استفاده كنند بايد اين ويزا را نشان دهند. خيلي هم خوبه اين ويزا داشتن . چون مثل رشته اي توابع را بهم مرتبط مي كند.

خط بعدي:
jc ErrorOpening ; jump if carry flag set - error!
اين هم يك پرش شرطي كه احتمالا به فلاگ cf نگاه مي كند. چون در اين برنامه و آموزش كه حرفي از فلاگ ديگري نبوده.

خوب نتيجه open فايل چي شد؟ شد يك هندل كه ريختيم در يك متغير و داريمش.
حالا برويم بقيه كدها را بخوانيم.

اين كد:
mov dx,offset Buffer ; address of buffer in dx
mov bx,Handle ; handle in bx
mov cx,100 ; amount of bytes to be read
mov ah,3Fh ; function 3Fh - read from file
int 21h ; call dos service

اول راهنماي ورودي و خروجي اين سرويس:
کد:
INPUT:

AH = 3Fh
BX = handle
CX = number of bytes to be read
DS:DX = segment:offset of a buffer

OUTPUT:

CF = 0 function is successful
AX = number of bytes read
CF = 1 an error has occurred
05h access denied
06h illegal handle or file not opened

اول شماره سرويس كه 3f است.
بعد هندل است كه بايد در bx وجود داشته باشد.
در cx هم تعداد بايتهايي كه بايد خوانده شود. ديگه شمارشگر بودن cx را خوب حس كرديم.

قضيه بعدي در كد برنامه ما اين:
mov dx,offset Buffer ; address of buffer in dx
است.
يعني كه ما آدرس بافر را مي دهيم تا هر چي از فايل خوانده شود برود داخلش.
از فايل به بافر. از هارد به ram (در قطعه داده).

حالا خروجي سرويس:
اول فلاگ cf است كه باز اگر صفر بود يعني كار خوانده موفقيت آميز بوده و در اين حالا تعداد بايتهاي خوانده شده در ax منعكس مي شود ،
و اگر عمل با شكست مواجه شود ، cf آنگاه (( يك)) خواهد شد.
و اينها:
05h access denied
06h illegal handle or file not opened
احتمالا ميرود داخل ax . من اينجا را نفهميدم.
در ادامه توضيحات سايت گفته كه اگر cf صفر شد و ax هم صفر بود ، يعني كه به اشاره گر به انتهاي فايل رسيده و بيشتر از اين نميشه خواند.
منظور از اشاره گر اينه كه وقتي از داخل فايل چيزي خوانده ميشه ، ميره خط بعد تا خط بعدي خوانده شود.
و اگر cf صفر بود و ax كوچكتر از cx بود ، يعني كه قسمتي از فايل خوانده شده و كار متوقف شده كه يا به علت رسيدن به انتهاي فايل بوده يا به علت رخ دادن خطايي.
اين چند خط توضيح را با اين :
05h access denied
06h illegal handle or file not opened
فكر كنم بشه يك جورايي با هم جمع كرد. خودتان تحقيق كنيد. من هم اگر جايي بود كه بهتر توضيح داده بود مي گويم.

برويم قسمت بعدي برنامه امان:
mov bx,Handle ; put file handle in bx
mov ah,3Eh ; function 3Eh - close a file
int 21h ; call DOS service

اين هم سرويس ديگري است كه 3e است و باز هندل مي خواهد . كارش هم بستن فايل است.
اين هم ورودي و خروجي اين سرويس:
کد:
INPUT:

AX = 3Eh
BX = file handle


OUTPUT:

CF = 0 function is successful
AX = destroyed
CF = 1 function not successful
AX = error code - 06h file not opened or unauthorised handle.

باز در خروجي به cf و ax ريخته ميشه كه اگر cf صفر باشه يعني موفقيت آميز و اگر cf يك باشد يعني شكست و كد خطا مي رود در ax .
نكته خطري اين close كردن:
اگر بدون هندل(يعني وقتي هندل صفر باشد) close كنيد ، ديگه شما فايل را close نكرده ايد و اينپوت استاندارد يعني كيبورد را close كرده ايد و ديگر هيچ چيزي نمي توانيد وارد كنيد.

خوب. خسته نباشيد.

===================================
انگار تكه آخر برنامه را توضيح نداديم. اين قسمت را:

mov cx,100 ; length of string
mov si,OFFSET Buffer ; DS:SI - address of string
xor bh,bh ; video page 11- 0
mov ah,0Eh ; function 0Eh - write character

NextChar:

lodsb ; AL = next character in string
int 10h ; call BIOS service
loop NextChar

به شرح سرويس 0E از وقفه 10 كه از آموزشهاي اموليتور نقل مي كنم توجه كنيد:
کد:
INT 10h / AH = 0Eh - teletype output.


input:
AL = character to write.
This functions displays a character on the screen,
advancing the cursor and scrolling the screen as necessary.
The printing is always done to current active page.

اين سرويس خروجي تله تايپ مي دهد.
اين سرويس چاپ مي كند و بعد كرزر را جلو مي برد و در صورت نياز صفحه را اسكرول مي كند . و در صفحه جاري مي نويسد.

و اينجا:
xor bh,bh ; video page – 0
آمده ايم با xor كردن ، bh را صفر كرده ايم. (تنظيم صفحه جاري.)
در :
mov cx,100 ; length of string
آمده ايم cx را تنظيم كرده ايم تا در لوپ استفاده شود.
اين خط هم:
mov si,OFFSET Buffer ; DS:SI - address of string
احتمالا براي استفاده lodsb است. اين كه مي گويم احتمالا چون من تا نروم با lodsb يك برنامه نسازم مطمئن نمي شوم. ولي همينه به احتمال زياد.
خلاصه تكه برنامه :

mov cx,100 ; length of string
mov si,OFFSET Buffer ; DS:SI - address of string
xor bh,bh ; video page - 0
mov ah,0Eh ; function 0Eh - write character

NextChar:

lodsb ; AL = next character in string
int 10h ; call BIOS service
loop NextChar

اين ميشه كه از قطعه داده در al بار ميشه با lodsb و بعد سرويس 0E از وقفه 10 مي آيد محتواي al را چاپ مي كند. و حلقه هم كارش اين است كه كار بار شدن و چاپ را 100 بار تكرار كند.
 
آخرین ویرایش:

saalek110

Well-Known Member
از صفحه 5 باز مانده كه ايجاد فايل – جستجوي فايل و غيره است كه فعلا حسش نيست بگم.
== = = = = = ==
اما راجع به پرشهاي شرطي عكس زير كه مقايسه بعضي پرشهاي شرطي با همتاي زبان سي است را مي گذارم كه فكر كنم جالب باشه.

a1.jpg

اين هم يك مثال از jnz :
کد:
MOV CX, 20            ;We will execute COUNT_LOOP 20 times
COUNT_LOOP:          ;Main entry point for loop
    DEC CX            ;Subtract 1 from CX
    JNZ COUNT_LOOP    ;If CX is zero, continue on to
                      ;next code, otherwise JMP back to COUNT_LOOP

يعني وقتي cx صفر بشه ديگه پرش انجام نميشه.
= = = = = == ==
اين هم يك مثال از jz :
کد:
MOV AX, 0010B ;move the decimal value '2' into the AX register
MOV CX, 0001B ;mov the decimal value '1' into the CX register
CMP AX, CX    ;Compare AX and CX by subtracting the contents of CX from AX
  JZ Was_zero  ;Jumpt to Was_zero label if result from CMP was ZERO
....       
....          ;Code to implement if Values were not equal

در كد بالا ،وقتي نتيجه تفريق(تفريق انجام نميشه با cmp ، فقط فلاگها تنظيم مي شوند. تفريق واقعي همان sub است. ) صفر باشد پرش مي كند.
 
آخرین ویرایش:

saalek110

Well-Known Member
ليست وقفه ها :
در اين سايت :
http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html

همان بالاي صفحه يك سري فايل براي دانلود هست كه من اولي را دانلود كردم.

اما با ديدن محتواي اين فايل كه پسوند هاي غيرمعمولي داشتند و با word و اديتور كدوايز توانستم باز كنم ، بايد بگم كه،

نه توصيه به دانلود مي كنم نه پرهيز از دانلود.

اگر مجموعه اي مي خواهيد و مي خواهيد كارهاي تحقيقي كنيد(عشق به اسمبلي – اعصاب و ...) ......
ولي اگر وقت نداريد و حوصله كم داريد.....
 

saalek110

Well-Known Member
اگر مي خواهيد برنامه اي داشته باشيد كه كليدي را از كيبورد بگيرد و ضمن نمايش آن حرف بر صفحه كد آن را هم در al بريزد، از برنامه زير استفاده كنيد.
کد:
.model small
.stack
.data
.code
asli proc
;------------------
mov ah, 1
int 21h
;------------------
mov ax,4c00h ; return to dos DOS
int 21h

asli endp
     end asli
برنامه بالا را من امتحان كردم. قبل اجراي وقفه و بعد آن آمدم al را چاپ كردم كه الو صفر بود بعد شد كد كاراكتر زده شده.
وقتي كليدي را بزنيم و آن كليد چاپ شود بر صفحه ، مي گوييم داراي اكو است.

اگر همين كار يعني گرفتن و ذخيره در al را بدون اكو مي خواهيد از سرويس 7 به جاي سروي 1 استفاده كنيد.
mov ah, 7


راهنماي آن:
کد:
INT 21h / AH=1 - read character from standard input,
with echo, result is stored in AL.
if there is no character in the keyboard buffer,
the function waits until any key is pressed.

example:


mov ah, 1
int 21h

قبلا من يك برنامه حلقه تو در تو ساختم تا وقفه زماني ايجاد كنم ولي وقفه اي هست كه تاخير ايجاد مي كند و راهنماي آن را در زير مي آورم. البته شايد وقفه هاي ديگري نيز براي اين كار باشد.
نكته : اين وقفه در ويندوز xp عمل نمي كند.
کد:
INT 15h / AH = 86h - BIOS wait function.
input:

CX:DX = interval in microseconds
return:

CF clear if successful (wait interval elapsed),
CF set on error or when wait function is already in progress.

Note:
the resolution of the wait period is 977 microseconds
on many systems (1 million microseconds - 1 second).
Windows XP does not support this interrupt (always sets CF=1).
اگر cf به يك تغيير كند به معني شكست كه در ويندوز ايكس پي بايد چنين شود.
همين طور كه در زير مي بينيد:
INT 15h / AH = 86h - BIOS wait function.
input:

CX:DX = interval in microseconds
شماره سرويس آمده و اين كه زمان دلخواه را بايد در چه رجيسترهايي بريزيم.
 
آخرین ویرایش:

saalek110

Well-Known Member
كار با ماوس:
وقفه 33 براي اين كار به كار مي رود.
براي استفاده از ماوس اول بايد راهش انداخت:
mov ax, 0 ; initilize mouse
int 33h

mov ax, 1 ; show mouse
int 33h
در دو سرويس بالا ، اولي اينيتيالايز و دومي show ماوس است. من امتحان كردم . يكي هم كه كم باشه ماوس نشان داده نمي شود.
به برنامه زير دقت كنيد:
کد:
.model small
.stack
.data
.code
asli proc
;------------------
mov ax, 0 ; initilize mouse
int 33h

mov ax, 1 ; show mouse
int 33h
;-------- wait ----------------
MOV AH,00H
INT 16H
;-------------------------------
mov ax, 2  ;makhfi kardane(hide) moushe
int 33h
;------------------
;-------- wait ----------------
MOV AH,00H
INT 16H
;-------------------------------
mov ax,4c00h ; return to dos DOS
int 21h

asli endp
     end asli

در اين برنامه ابتدا ماوس اينيتيالايز و show شده.
بعد من با دو خط كد حالت انتظار در برنامه بوجود آورده ام براي گرفتن كليدي.
و با زدن كليد مي رود به دو خط بعدي. يعني:
mov ax,4c00h ; return to dos DOS
int 21h
اين دو خط ماوس را hide ، يعني مخفي مي كند. اگر اين دو خط نباشد بعد اختتام برنامه هم باز ماوس وجود خواهد داشت.
من يك wait هم بعد خاموشي ماوس گذاشته ام در كد بالا ، تا خاموشي ماوس را ببينيد.

نكته: در حالت full screen بايد ماوس را ببينيد. با همين نام دكمه اي روي تولبار پرومپت داس خود داريد كه آن را بزنيد.

= == = = = = == = = =
نكات ماوس:
اول راهنماي اينيتيالايز:
کد:
INT 33h / AX=0000 - mouse ininialization. any previous mouse pointer is hidden.

returns:
if successful: AX=0FFFFh and BX=number of mouse buttons.
if failed: AX=0

با موفقيت آميز بودن ax مساوي 0ffff و bx مساوي تعداد دكمه هاي ماوس مي شود. و در صورت شكست ax صفر مي شود. من امتحان كردم به من ffff داد ax را و عدد 2 براي bx . ماوس من دو دكمه چپ كليك و راست كليك دارد. شايد براي اين است. وسط كليك ندارد.
= = =
سرويس show و hide راهنما ندارد.

در برنامه بالا ، سرويس هاي صفر و يك و دو استفاده شده بود براي اينيتيالايز و show و hide .
سرويس ديگري داريم با شماره 3 .
راهنما:
کد:
INT 33h / AX=0003 - get mouse position and status of its buttons.

returns:
if left button is down: BX=1
if right button is down: BX=2
if both buttons are down: BX=3
CX = x
DX = y
example:

mov ax, 3
int 33h

; note: in graphical 320x200 mode the value of CX is doubled.

مي دانيد كه برنامه قبلي ما كار خاصي انجام نمي داد. چون فقط روشن و خاموش مي كرد ماوس را. اصل قضيه همين سرويس 3 است. حالا چه برنامه اي بنويسيم تا اين را بكار ببريم؟!
يك حلقه خوبه نه؟ كه مدام مختصات ماوس را نشان دهد.
در راهنماي بالا مي بينيد كه مختصات ماوس در cx و dx ريخته مي شود. پس من در زير برنامه اي مي گذارم كه در حلقه اي مدام cx و dx را چاپ كند:
کد:
.model small
.stack
.data
.code
asli proc
;------------------
mov ax, 0 ; initilize mouse
int 33h

mov ax, 1 ; show mouse
int 33h
;========= halgheh =================
lable_first:
;---------service 3
mov ax, 3
int 33h
;---------curser be avale safeh
push dx
mov dh,0  ;DH = row.
mov dl,0  ;DL = column.
mov bh,0
mov ah,2  ;service
int 10h
pop dx
;------------------------------

mov bl,ch
call bl_print
mov bl,cl
call bl_print

mov bl,dh
call bl_print
mov bl,dl
call bl_print

jmp lable_first
;=================================
mov ax, 2  ;makhfi kardane(hide) moushe
int 33h
;------------------
mov ax,4c00h ; return to dos DOS
int 21h

asli endp
; ============ sub bl_print ===========
bl_print PROC NEAR
push ax
push bx
push cx
push dx
;----------part 1
mov ah,2h
mov dl,bl 

mov cl,04h
shr dl,cl

add dl,30h

cmp dl,3ah
jl lable1

add dl,07h

lable1:
int 21h

; -----------part 2

mov dl,bl
and dl,0fh

add dl,30h

cmp dl,3ah
jl lable2

add dl,07h

lable2:
int 21h
;------------
pop dx
pop cx
pop bx
pop ax

ret ; return to where it was called
bl_print ENDP
;================================

     end asli

شرح برنامه:
يك حلقه با دستور jmp يعني جامپ ساخته شده كه با خطهايي كه با مساوي كشيده ام ، محدوده حلقه مشخص شده. قبل حلقه هم كه ماوس قبلا روشن شده بود.
اما ، داخل حلقه ، اول ليبل است كه جامپ به آنجا انجام مي شود. بعد سرويس 3 از وقفه 33 را داريم. و بعد هم 7 خطي كه كرزر را به اول صفحه مي برد. مي توانيد اين 7 خط را حذف كنيد ولي با اين كار اعداد همين طور به پايين مي روند و منظره خوبي ندارد.
بعد اين 7 خط هم من با صدا كردن bl_print آمده ام cx و dx را چاپ كرده ام.

كار قشنگ تر اينه كه cx و dx را چاپ نكنيم. بلكه در مكان موس كاري چاپي انجام بشود كه خودتان برنامه اش را بسازيد.
آخرين خط داخل حلقه هم همان دستور جامپ است.
== = == = =
بايد برنامه اي هم بنويسيد براي دريافت bx براي تست اين قسمت:
if left button is down: BX=1
if right button is down: BX=2
if both buttons are down: BX=3
براي اين كار به جاي اين قسمت در برنامه بالا:
;---------curser be avale safeh
push dx
mov dh,0 ;DH = row.
mov dl,0 ;DL = column.
mov bh,0
mov ah,2 ;service
int 10h
pop dx
;------------------------------

mov bl,ch
call bl_print
mov bl,cl
call bl_print

mov bl,dh
call bl_print
mov bl,dl
call bl_print
اين قسمت را جايگزين كنيد:
;---------curser be avale safeh
push bx
mov dh,0 ;DH = row.
mov dl,0 ;DL = column.
mov bh,0
mov ah,2 ;service
int 10h
pop bx
;------------------------------

push bx
mov bl,bh
call bl_print
pop bx
call bl_print

با اين جايگزيني ، باعث چاپ bx مي شويد و با كليك چپ عدد ((يك)) و با كليك راست عدد ((دو)) چاپ مي شود.

اما در قسمت جايگزين شده دقت كنيد كه اطراف آن 7 خط انتقال كرزر قبل جايگزيني من dx را push كردم و بعد جايگزيني bx را push كردم . چون در برنامه اول ما مي خواستيم dx را چاپ كنيم ولي در برنامه دوم مي خواستيم bx را چاپ كنيم.

در قسمت جايگزين شده به اين خط ها نگاه كنيد:
push bx
mov bl,bh
call bl_print
pop bx
call bl_print
در خط :
mov bl,bh
مي بينيد كه bl دارد نابود مي شود ، در صورتي كه بايد در خطهاي بعدي چاپ شود. پس قبل نابودي اش من آنرا push كرده ام تا مصون بماند. و بعد pop مستقيما آمده ام bl_print را احضار كرده ام چون ديگه نياز نيست كه bl را روي bl بريزم.

نكته: در مود كاراكتري موس به شكل مستطيل است و در مود گرافيكي به شكل رايج موس يعني فلش مانند.
همچنين در اين پست در راهنماها به تغيير اندازه اي در مود گرافيكي اشاره شده كه به آن توجه كنيد.

; note: in graphical 320x200 mode the value of CX is doubled.
 
آخرین ویرایش:

saalek110

Well-Known Member
این برنامه نوعی تمرین بر مباحث قبلی است. کار این برنامه چاپ یک رجیستر در مبنای 2 است.
کد:
.model small
.stack 
.data 
.code 
asli proc
;------------------------------------
mov bl,6

mov ah,2
mov cx,8
my_lable:
mov dl,0
rcl bl,1
adc dl,30h
int 21h
loop my_lable
; -------- key --------------
xor ax,ax ; function 00h - get a key
int 16h ; call BIOS service
; ---------------------------
;-------------------------------------
mov ax,4c00h ; return to dos DOS 
int 21h 

asli endp
     end asli
برنامه را بین دو خط افقی محصور کردم تا با قالب برنامه که شما می توانید قالب دلخواه خود را جایگزین کنید مخلوط نشود.
یک تکه هم که باز با خط افقی محصور شده و با کلمه key عنوان داده شده همان طور که در برنامه های قبلی هم بکار بردیم برای این است که بعد چاپ نتایج برنامه از حالت اجرا خارج نشود تا ما بتوانیم نتیجه اجرا را ببینیم. تا کلیدی زده نشود برنامه به پایان نمی رسد.

شرح برنامه:
در خط اول یعنی
mov bl,6
به bl مقدار اولیه داده ایم. عدد 6 یعنی که بیت دوم و سوم عدد از سمت راست باید 1 باشد و بقیه صفر باشد. برای سادگی این عدد را انتخاب کرده ام. البته با اعداد دیگر هم امتحان کرده ام من ولی با اجرای برنامه بالا باید به:
00000110
برسید.
یعنی همان 6 در مبنای 2 . اگر می خواهید همه یک شوند باید به bl مقدار0ffh بدهید. می دانید که اگر عددی با حرف شروع شود یک صفر قبل آن باید گذاشت.

خط دوم یعنی
mov ah,2
که می دانید آمادگی چاپ است برای وقفه
int 21h

بقیه برنامه را کلی توضیح می دهم چون همه به هم مربوط است.
ما می آییم bl را با دستور rcl چرخش می دهیم. دستور چرخش با دستور شیفت که قبلا در این تاپیک استفاده کردیم فرق دارد. در چرخش عدد از آن طرف دوباره به خود برمیگردد. شما اینجا بیتهای bl که 8 تا است (و به همین دلیل cx که تعداد چرخش حلقه است 8 تنظیم شده) و بیت فلاگ نقل را با هم در نظر بگیرید.
یک چرخش بین این 9 بیت در جریان است. یعنی هر بیت اول به فلاگ نقل می رود و بعد از آن طرف دوباره وارد bl می شود. و وقتی محتوای بیت داخل فلاگ نقلی است فرصت خوبی است تا آن را چاپ کنیم. فکر کنم دستورات دیگر هم باشد که چرخش بدهد ولی داخل فلاگ نقلی نیاندازد ولی برای ما در اینجا رفتن به فلاگ نقل یک فرصت است.
دستور adc قبلا هم شرح داده شده در این تاپیک. ولی باز می گویم . کارش این است که دو عدد را جمع می کند و همزمان با جمع دو عدد می آید فلاگ نقل را هم جمع می زند. ما آمده ایم با 30h جمع زده ایم تا موقع چاپ ((صفر یا یک )) چاپ شود. قبلا در برنامه bl_print شرح دادیم که فلسفه این عدد 30h چیست.
فکر کنم توضیح کافی باشد. با تغییر دادن برنامه می توانید بیشتر بفهمید که کار هر دستور چیست.
 

saalek110

Well-Known Member
مطلب زیر هم برای یک مرور فکر کنم دید بدهد:
از تاپیک: آموزش crack...فقط علاقه مندان لطفاً
http://forum.persiantools.com/showthread.php?t=2701

os ها يکی از کاراشون اجرا برنامه ها هست...هر os يک نوع خاص از برنامه ها رو اجرا ميکنه...مثلاً Wav,txt,exe و غيره
اما بعضی از این فرمت ها نشان دهنده اینند که این برنامه ها بايد کد داخلشون اجرا بشه..مثل exe و com و همچنين dll,ocx,vxd همه اینها به نوعی شامل کد
اجرايی ميباشند...این کد ها بوسيله زبان های برنامه نويسی نوشته ميشوند مثلاً برلند پاسکال!
کاری که این compiler ها انجام ميدهند تبديل زبانی که شما استفاده کرديد به زبان کامپيوتر بعلاوه اضافه کردن
يک مشت guideline برای osای که شما ميخواهيد برنامه شما در آن اجرا شود.
در سيستم های ويندوز اکثراً نوع فايل ها از پسوند آنها مشخص ميشوند..ما این فرمت ها را برای برنامه های اجرايی داريم:exe,ocx,dll,vxd اینها تقريباً مهمترين ها هستند که
شما با اکثر compiler ها ميتونيد برای این حالات برنامه بنويسيد...

الان کمتر از بافت com استفاده ميشود اما بهترين بافت برای يادگيری برنامه نويسی به زبان اسّمبلی هست..چون هيچ گونه فرمت خاصی ندارد
و از ابتدا فايل کد اجرايی ميباشد...

اما اینها اصلاً به چه درد ميخورند؟!!
شما برای crack کردن و يا يادگی نحوه نوشته شدن برنامه خاصی قاعدتاً نياز به تحقيق در فايل اجرايی آن برنامه داريد!
برای همين معمولاً در ويندوز فايل های اجرايی دارای پسوند exe هستند پس شما بايد فايل exe را بخوبی بشناسيد!!
کمتر با com,ocx,vxd برخورد ميکنيد و فکر نکنم ما هيچ وقت به اون مرحله برسيم اما يک برسی هم برای فايل dll ميگزارم
چون امکان برخورد با این فايل رو هم خواهيد داشت!

اما خوب ما اصلاً چگونه يک برنامه/فايل اجرايی رو ميخواهيم برسی کنيم؟
فعلاً در ابتدا نيازی به برسی به صورت binary فايل exe نخاهيم داشت اما نياز به يک dissassembler و يا يک debugger خواهيم داشت.
اما اینها اصلاً چی هستند؟
dissassembler برنامه شما رو تبديل به برنامه ای با کد assembly ميکند و با debugger هم شما ميتونيد کد assembly را ببينيد...اما خوب چه فرقی ميکنند...
ببينيد تمامی برنامه های اجرايی در سيستم های intel based از يک کد زبن استفاده ميکنند که در هر صورت برنامه شما بايد تبديل به این کد ها شود برای قابل فهم شدن برای کامپيوتر شما
اما ما يک زبان macro assembly داريم که کمی پيشرفته تر از assembly شايد بشه گفت هست و اینکه شما يک راست کد نميکنيد چون
هيچ وقت اطلاع درستی از آدرس های حافظه نداريد برای همين باز هم کد assembly خوب را به يک COMpiler ميفرستيد تا به خوبی تبديل به يک برنامه قابل فهم بشه
کل این حرفا بدين معنی که debugger ها هرچند که هدف اصليشون debug کردن و يافتن مشکلات در برنامه ها هست اما
باز هم به خوبی امکان برسی را به ما ميدهند و debugger ها در حقيقت فقط قسمت کوچکی از حافظه را
disassemble ميکنند اما dissassembler ها سعی ميکنند که کل برنامه را به يکديگر ارتباط داده و نشان دهند
به همين علت dissassembler ها در اکثر مواقع مشکلتی در نمايش کد خواهند داشت اما debugger ها نه؟

حالا ما چه استفاده ای از debuger ميکنيم؟
ما برنامه را از ابتدا با debuger اجرا ميکنيم و پله پله با برنامه پيش ميريم بدين ترتيپ ميتونيم بفهميم که
هدف برنامه نويس از این کد ها چه بوده و چگونه این کار را انجام داده...که ميبينيد برای این کار نياز به دانستن
assembly خواهيد داشت...البته خوب شايد برتون سؤال پيش بياد که اینجوری چرا مثلاً ملت چرا از code های ديگران استفاده نميکنند
و يا مثلاً رقبا با این کار پی به رمز نوشته شدن این برنامه نميبرند؟؟؟
اگر برنامه نويس باشيد حتماً توجه کرديد که خواندن برنامه فرد ديگر چقدر سخت است...
حال در نظر بگيريد که خواندن برنامه طرف آن هم در زبان assembly و با n برابر شدن مقدار source آيا ميشود يا نه؟؟؟؟
که البته هدف از reverse engeeniring هم همين است که سعی ميشود با کارهايی این فرايند ساده تر شود و بتونيم چنين کاری انجام دهيم

چگونه ما حافظه رو آدرس دهی ميکنيم؟

برای راحتی به این نتيجه رسيدند که بهترين کار بری حافظه تبديل آن به واحد های بزرگ و سپس تبديل آن به واحد
های کوچکتر هست.

!!!!!!!!!!!!!!!!
البته يک نکته که بحث اسمبلی ما فعلاً در محدوده پردازنده های 16 بيتی هست و وابسته به interl architecture
تمامی این بحثا در غير intel based ها منتفی هست(amd هم اینتل based هست ناراحت نشيد)
!!!!!!!!!!!!!!!!!

چرا 16 بيت؟برای اینکه پردازنده ما 16 بيت هست بدين معنی که تمامی کرها با 16 بيت انجام ميشه و در نتيجه
ثبات ها نيز 16 بيتی هستند که با اینها ما آدرس دهی ميکنيم(more on this later)

پس محدوده مجاز برای ما از 0000h )h برای نشان دادن hex بودن عدد بکار ميرود)تا
FFFFh که ميشود 64kb.
البته این خيلی کم هست اما با ایجاد تکنيکی که از 20 بيت برای آدرس دهی استفاده ميشود این مقدار افزيش پيدا
کرد.
آدرس ها به شکل segment و offset تقسيم ميشوند و آدرس واقعی با جمع ایندو حاصل ميشود
پس آدرس موثر=segment + offset
پس با بالا و پايين کردن offset ميتوانيم يک محدوده 64k را نيز پوشش بديم.
حرکت آدرس موثر در محدوده 00000H تا FFFFFH خواهد بود که در نتيجه با داشتن این 20 بيت ميتوانيم
1mg را آدرس دهی کنيم(و صد در صد نه 640kb که اکثراً به اشتباه فکر ميکنند)

يک نکته بسيار مهم اینجاست به پين توجه کنيد!!
Segment Offset effective addres
8000h 1111h 81111h
8001h 1110h 81111h
نکته بسيار مهمی هست ها...روش فکر کنيد چرا...
اما چگونه آدرس را نشان ميديم به این شکل segment : offset که حتماً بعداً خواهيد ديد.

همينجا pascal کاران عزيز و احتمالاً basic کاران(داس) فهميدند که چرا نميتونستيد يک آرايه بزرگتر از 65536 بسازيد
و يا error هايی چون data segment is full رو مواجه ميشديد!!چرا؟

يک نکته ديگر هم اینکه باز تمامی این مطالب بيشتر در real-mode کاربرد دارند و نه Virtual/protected mode
که کل این مباحث به شکل ديگری هستند؟اگر نمدونيد فرق REal با PRotected چی هست هم خوب اگر وقت شد توضيح ميدم اما
اونهمه مهم نيست!

نکته مهم ديگری که هست این است که Intel 80XX family به صورت little endian مقادير را در حافظه نگاه داری ميکنند
که باعث اکثر اشتباهات شما همين دردسر خواهد بود...
بديم معنی که مقادير را وارونه در حافظه نگاه داری ميکنن و هميشه مقادير پايينی اول مياند و بعد بالايی
يعنی اگر عدد 1234H را ذخيره کنيد در آدرس 100h در 100h خواهيد داشت 34 و در 101h خواهيد داشت 12h
مسخرست نه؟به هر حال خيلی خيلی خيلی مهم هست...مخصوصاً در crack که بايد يادتون باشه اینها رو برای ياداشت
کردن وارونه کنيد!1(البته اکثر برنامه ها این عمل رو از شما مخفی ميکنند اما توصيه من اینه که بفهميد چی به چی شد)
البته توجه کرديد که گفتم مقادير پايين و بالا...حالا بگيد ببينم اگر يک مقدار 4 word رو نگاه داريم چجوری ذخيره ميشه؟!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1 byte=byte
2 byte=word
3 byte= نداريم
4 byte= DWord(Double Word)
8 byte=Quad Word
16 byte=Paragraph
این 2 تا آخری البته به دردتون نميخوره
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 

saalek110

Well-Known Member
مهر 1398:
up
از مدیر تالار درخواست کردم قفل تاپیک را بردارد تا پستهای خودم را در این تاپیک اصلاح کنم.
در صفحه 2 یعنی شروع پستهای خودم فایلهای ضروری را ضمیمه کردم. و یک عکس را جایگزین کردم.
من فایلهای asm یعنی سورس اسمبلی را با Tasm تبدیل می کردم. ولی الان ویندوز من 64 بیت است و Tasm کار نمی کند. ممکن است ویندوز شما 32 بیت باشد و Tasm برای شما کار کند.
به نظرم بهتر است پستهای این تاپیک بهم نخورد. این تاپیک برای ویندوز 32 بیت مناسب است.
یک سری عکس بود بخاطر ازبین رفتن هاست مجانی عکس آدمک نشان می داد که عکسها را با عکسی حاوی نوشته no image جایگزین کردم.a1.jpg چون ویندوز من الان 64 بیت است و نمی توانم با کدها کار کنم پس قادر به تهیه مجدد عکسها نبودم.
 
آخرین ویرایش:
وضعیت
موضوع بسته شده است.

جدیدترین ارسال ها

بالا