Основные сведения о листинге и его структуре
Листинг (распечатка) программы на ассемблере используется как при создании ассемблерных программ, так и в качестве источника информации для квалифицированных программистов при отладке и оптимизации программ, написанных на языках высокого уровня. Ни один другой компилятор и его листинг не дает программисту такого количества полезной технической информации, как ассемблер. Ведь одна из основных целей использования языков высокого уровня — как раз желание избежать не очень существенных технических подробностей. Но если программист хочет разобраться с подробностями созданной программы, то большинство отладчиков могут распечатать объектный эквивалент созданной программы на языке ассемблера. Эти распечатки позволяют программисту оценить качество программы и являются весьма полезными при ее оптимизации.
Листинг состоит из 2-х частей: из листинга программы и сводной информации о сегментах и идентификаторах программы.
Листинг программы имеет три столбца, в которых отображаются команды исходной ассемблерной программы и соответствующие им объектные коды:
l левый столбец содержит шестнадцатеричное значение смещения адреса команды (счетчик команд — IP) от начала сегмента;
l правый столбец содержит операторы и псевдооператоры ассемблера (команды и директивы программы);
l в средней части размещены коды: для сегмента стека и сегмента данных — числа, запоминаемые в соответствующих ячейках памяти; для сегмента команд это коды машинных команд МП, соответствующих операторам ассемблера.
Сводная информация о сегментах и идентификаторах дает подробную их характеристику.
В конце листинга приводятся сообщения об ошибках в программе.
Ниже приводится алгоритм (рис. 18.2), программа вычисления квадратного корня числа n и листинг этой программы.
TITLE SQR.ASM ; Извлечение корня квадратного
stacksg segment para stack 'Stack'
; назначить область памяти для стека
dw 32 dup(32)
stacksg ends
datasg segment para 'Data'
; определить данные
vv db 'введите аргумент n (до 64 тыс.) $'
viv db 10,13,'значение корня = $'
sr db 3 dup(0)
db 13,10,'$'
buf db 5,0,0,0,0,0,0,0
n dw ?
e dw 1
a dw ?
b dw ?
val dw ?
two dw 2
datasg ends
codesg segment para 'Code'
; программный сегмент
assume cs:codesg,ds:datasg,ss:stacksg
begin proc far
push ds
sub ax,ax
push ax
mov ax,datasg
mov ds,ax
mov ah, 9
mov dx,offset vv
int 21h
mov ah, 0ah
mov dx,offset buf
int 21h
call str2bin
mov dx,0
mov ax,n
inc ax
div two
sub dx,dx
mov a,ax
iter: mov ax,n
div a
add ax,a
mov dx,0
div two
sub dx,dx
mov b,ax
sub ax,a
cmp ax,e
jbe met
mov ax,b
mov a,ax
jmp iter
met: mov ah,9
mov dx,offset viv
int 21h
call bin2str
mov ah,9
mov dx,si
int 21h
ret
bin2str proc near
mov cx,10
mov si,offset sr+2
mov ax,b
m1: sub dx,dx
div cx
or dl,30h
mov [si],dl
dec si
cmp ax,0
jne m1
ret
bin2str endp
str2bin proc near
mov di,1
mov cx,0ah
mov si,offset buf+1
sub bh,bh
mov bl,[buf+1]
m2: mov al,[si+bx]
and ax,0fh
mul di
add n,ax
mov ax,di
mul cx
mov di,ax
dec bx
jnz m2
ret
str2bin endp
begin endp
codesg ends
end begin
Рис. 18.2 Алгоритм извлечения квадратного корня из числа n
Листинг программы SQR.ASM.
Microsoft (R) Macro Assembler Version 5.10 3/19/04 23:44:19
SQR.ASM ; Извлечение корня квадратного
TITLE SQR.asm ; Извлечение корня квадратного
0000 stacksg segment para stack 'Stack'
; назначить область памяти для стека
0000 0020[ dw 32 dup(32)
]
0040 stacksg ends
0000 datasg segment para 'Data'
; определить данные
0000 A2 A2 A5 A4 A8 E2 vv db 'введите аргумент n (до 64 тыс.)$'
A5 20 A0 E0 A3 E3
AC A5 AD E2 20 6E
20 28 A4 AE 20 36
34 20 E2 EB E1 2E
29 20 24
0021 0A 0D A7 AD A0 E7 viv db 10,13,'значение корня = $'
A5 AD A8 A5 20 AA
AE E0 AD EF 20 20
3D 20 24
0036 0003[ sr db 3 dup(0)
]
003A 0D 0A 24 db 13,10,'$'
003D 05 00 00 00 00 00 buf db 5,0,0,0,0,0,0,0
00 00
0045 0000 n dw ?
0047 0001 e dw 1
0049 0000 a dw ?
004B 0000 b dw ?
004D 0000 val dw ?
004F 0002 two dw 2
0051 datasg ends
0000 codesg segment para 'Code'
; программный сегмент
assume cs:codesg,ds:datasg,ss:stacksg
0000 begin proc far
0000 1E push ds
0001 2B C0 sub ax,ax
0003 50 push ax
0004 B8 ---- R mov ax,datasg
0007 8E D8 mov ds,ax
0009 B4 09 mov ah, 9
000B BA 0000 R mov dx,offset vv
000E CD 21 int 21h
0010 B4 0A mov ah, 0ah
0012 BA 003D R mov dx,offset buf
0015 CD 21 int 21h
0017 E8 007D R call str2bin
001A BA 0000 mov dx,0
001D A1 0045 R mov ax,n
0020 40 inc ax
0021 F7 36 004F R div two
0025 2B D2 sub dx,dx
0027 A3 0049 R mov a,ax
002A A1 0045 R iter: mov ax,n
002D F7 36 0049 R div a
0031 03 06 0049 R add ax,a
0035 BA 0000 mov dx,0
0038 F7 36 004F R div two
003C 2B D2 sub dx,dx
003E A3 004B R mov b,ax
0041 2B 06 0049 R sub ax,a
0045 3B 06 0047 R cmp ax,e
0049 76 08 jbe met
004B A1 004B R mov ax,b
004E A3 0049 R mov a,ax
0051 EB D7 jmp iter
0053 B4 09 met: mov ah,9
0055 BA 0021 R mov dx,offset viv
0058 CD 21 int 21h
005A E8 0064 R call bin2str
005D B4 09 mov ah,9
005F 8B D6 mov dx,si
0061 CD 21 int 21h
0063 CB ret
0064 bin2str proc near
0064 B9 000A mov cx,10
0067 BE 003A R mov si,offset sr+2
006A A1 004B R mov ax,b
006D 2B D2 m1: sub dx,dx
006F F7 F1 div cx
0071 80 CA 30 or dl,30h
0074 88 14 mov [si],dl
0076 4E dec si
0077 3D 0000 cmp ax,0
007A 75 F1 jne m1
007C C3 ret
007D bin2str endp
007D str2bin proc near
007D BF 0001 mov di,1
0080 B9 000A mov cx,0ah
0083 BE 003E R mov si,offset buf+1
0086 2A FF sub bh,bh
0088 8A 1E 003E R mov bl,[buf+1]
008C 8A 00 m2: mov al,[si+bx]
008E 25 000F and ax,0fh
0091 F7 E7 mul di
0093 01 06 0045 R add n ,ax
0097 8B C7 mov ax,di
0099 F7 E1 mul cx
009B 8B F8 mov di,ax
009D 4B dec bx
009E 75 EC jnz m2
00A0 C3 ret
00A1 str2bin endp
00A1 begin endp
00A1 codesg ends
end begin
Segments and Groups:
N a m e Length Align Combine Class
CODESG . . . . . . . . . 00A1 PARA NONE 'CODE'
DATASG . . . . . . . . . 0051 PARA NONE 'DATA'
STACKSG . . . . . . . . 0040 PARA STACK 'STACK'
Symbols:
N a m e Type Value Attr
A . . . . . . . . . . . L WORD 0049 DATASG
B . . . . . . . . . . . L WORD 004B DATASG
BEGIN . . . . . . . . . F PROC 0000 CODESG Length = 00A1
BIN2STR . . . . . . . . N PROC 0064 CODESG Length = 0019
BUF . . . . . . . . . . L BYTE 003D DATASG
E . . . . . . . . . . . L WORD 0047 DATASG
ITER . . . . . . . . .. L NEAR 002A CODESG
M1 . . . . . . . . . .. L NEAR 006D CODESG
M2 . . . . . . . . . .. L NEAR 008C CODESG
MET . . . . . . . . . . L NEAR 0053 CODESG
N . . . . . . . . . . . L WORD 0045 DATASG
SR . . . . . . . . . .. L BYTE 0036 DATASG Length = 0004
STR2BIN . . . . . . . . N PROC 007D CODESG Length = 0024
TWO . . . . . . . . . . L WORD 004F DATASG
VAL . . . . . . . . . . L WORD 004D DATASG
VIV . . . . . . . . . . L BYTE 0021 DATASG
VV . . . . . . . . . .. L BYTE 0000 DATASG
@CPU . . . . . . . . .. TEXT 0101h
@FILENAME . . . . . . . TEXT sqr3
@VERSION . . . . . . .. TEXT 510
95 Source Lines
95 Total Lines
28 Symbols
47690 + 382785 Bytes symbol space free
0 Warning Errors
0 Severe Errors
При ассемблировании и редактировании связей могут быть получены еще два листинга с дополнительной информацией:
l карта перекрестных ссылок указывает номер строки программы, в которой определен каждый идентификатор, и номер тех строк, в которых имеются на него ссылки (этот листинг можно получить, если на запрос ассемблера о перекрестных ссылках (Cross references) ввести имя файла prog (а не Nul.CRF — по умолчанию), при этом в основном листинге программы добавится столбец с номерами строк);
l карта распределения памяти содержит подробные сведения о сегментах всех блоков программы, объединяемых редактором связей LINK (листинг содержится в файле prog.map).