Консультация № 186329
06.06.2012, 17:58
136.87 руб.
0 21 1
Здравствуйте, уважаемые эксперты. Есть простейшая программа, выводит "Hello, World!", вот она:
Код:
.model small
.stack 100h
.data
msg db 'Hello, World!$'
.code
start:
mov ax,@data
mov ds,ax

mov ah,9
mov dx,offset msg
int 21h

mov ax,4c00h
int 21h
end start

Просматривая дамп, получил странную картину(прилагаю): данные идут не с нуля, как в коде, а с некоторым смещением. Проверял на других программах, то же самое. Заметил, что перед данными каким-то образом влезает хвост программы из сегмента кода. Изменил код с упрощенной записи(.model small и т.п.) на классическую - баг изчез. Что бы это могло быть, и можно ли исправить?

Обсуждение

давно
Посетитель
7438
7205
06.06.2012, 18:22
общий
А Вы каким Ассемблером пользуетесь?
Мой tasm 4.1 формирует сегменты с выравниванием на параграф, т.е. на адрес 10h
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
06.06.2012, 18:26
общий
У меня такой же, TASM 4.1
давно
Старший Модератор
31795
6196
06.06.2012, 18:31
общий
Странно масм и тасм дают правильный результат:

У меня ХР сп3, какая у Вас ОСЬ и компилятор?
Проверьте HIEW'ом формирование кода, возможно настройки компилятора по умолчанию сбиты:
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
06.06.2012, 18:38
общий
06.06.2012, 18:43
Вот скрин с hv:

Система тоже XP sp3
Символы '*' я уже потом добавил, чтобы убедиться, что хвост вылезает.
Неизвестный
06.06.2012, 19:12
общий
Установил MASM6.11 - та же история. Получается, сегмент данных почему-то не выравнивается на параграф, ни в МАСМе, ни в ТАСМе. Видимо, дело не в компиляторе?
давно
Старший Модератор
31795
6196
06.06.2012, 19:32
общий
06.06.2012, 19:34
Скорее всего у Вас сбился макрос [i].CODE[/i], т.е. вместо положенного PARA, установленно меньшее значение:

Цитата: Зубков
имя_сегмента segment readonly выравн. тип разряд 'класс'


Цитата: Зубков
Выравнивание. Указывает ассемблеру и компоновщику, с какого адреса может начинаться сегмент. Значения этого операнда:
BYTE — с любого адреса;
WORD — с четного адреса;
DWORD — с адреса, кратного 4;
PARA — с адреса, кратного 16 (граница параграфа);
PAGE — с адреса, кратного 256.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
06.06.2012, 19:44
общий
Цитата: 335419
Установил MASM6.11 - та же история. Получается, сегмент данных почему-то не выравнивается на параграф, ни в МАСМе, ни в ТАСМе. Видимо, дело не в компиляторе?

Скачал TASM 4.1, формирует код нормально.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
06.06.2012, 19:58
общий
Адресаты:
Большое Вам спасибо! Получилось. Видимо, в самом деле был поврежден макрос.
Неизвестный
06.06.2012, 21:53
общий
06.06.2012, 22:01
Хех.. Все дело оказалось в моей криворукости)). И компилятор ни причем. Тестируемый файлик hello.asm я поместил в папку BIN свежескачанного ТАСМА, сделал .exe и возрадовался, данные идут с нуля. Делаю рабочую папку WORK в другом месте, собираю там другую программу, снова та же ерунда. И тут я вспомнил, что не так давно ставил Turbo C, в котором тоже есть TLINK, посмотрел path, оказалось, что он у меня прописан раньше, чем TLINK тасмовский. Вот он-то, наверное, и собирал неправильно exe-файл. Изменил path, теперь порядок. Все равно, спасибо за помощь!
давно
Посетитель
7438
7205
06.06.2012, 22:37
общий
Адресаты:
Ну так, можно и ответ оформить...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
07.06.2012, 10:11
общий
07.06.2012, 10:12
Цитата: 335419
И тут я вспомнил, что не так давно ставил Turbo C, в котором тоже есть TLINK, посмотрел path,

С ТАСМом возможно, но как быть с
Цитата: 335419
Установил MASM6.11 - та же история.

В комплекте идет LINK, а не TLINK. Влиять не должны.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
07.06.2012, 12:04
общий
До изменения path проверил, линкует TLINK 2.0(из TURBO C), после исправления стал линковать TLINK 7.1.30.1(из TASM). Так что насчет TASMа моя догадка оказалась верной. С MASMом действительно ничего не изменилось. Скачал и установил заново - не помогло. Делал так:

Неизвестный
07.06.2012, 12:31
общий
Попробовал сейчас, как и с TASMом, сделать .exe в самой папке BIN MASMа, но на этот раз результат не изменился. Значит тут дело в чем-то другом.
давно
Старший Модератор
31795
6196
07.06.2012, 12:40
общий
У меня такой-же линекер как и у Вас.
Сейчас буду смотреть что в системных параметрах.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
07.06.2012, 13:12
общий
Хорошо, буду ждать. Наверное я Вас уже замучил своей головоломкой
давно
Старший Модератор
31795
6196
07.06.2012, 16:59
общий
07.06.2012, 17:01
Разбираясь, набрел на такую страницу:
Цитата: URL >>
И еще с выравниванием сегментов, при использовании упрощенных директив сегментации, происходит какая-то свистопляска :). Все это выявлено опытным путем.

На следующих страницах идет обсуждение именно компиляции кода с помощью ТАСМ и МАСМ URL >>:

упрощенные директивы TASM, расположили сперва код, потом данные, потом стек. Причем хотя для данных в листинге видим выравнивание типа WORD, по факту TASM сделал выравнивание типа PARA, что видно на скрине экзешника


MASM обошёлся с атрибутами выравнивания более праведным образом. Из скрина EXE видно, что данные выравнены в соответствии с атрибутом WORD, что соответствует листингу программы. Соответственно размер программы оттранслированной MASM меньше на 14 байт, чем то, что сделал TASM.


Теперь почему именно WORD
Упрощенные директивы сегментации имеют свои аналоги:
[table][row][col].code[/col][col] _TEXT segment word public ’CODE’[/col][/row]
[row][col].stack[/col][col] STACK segment para public ’stack’[/col][/row]
[row][col].data [/col][col]_DATA segment word public ’DATA’[/col][/row][/table]
Данные и код выравниваются на слово, а стек на параграф.
Даже МАСМ 5.1 делает выравнивание в слово, но в его дебрях я нашел макрос EXTENDA.INC:
[code h=200]$cseg macro p1
if $$cseg
$err <already have CODESEG>
else
$cbeg macro
$gen <p1 SEGMENT BYTE PUBLIC 'CODE'>
endm
$cass macro
$gen < ASSUME CS:&p1, DS:NOTHING, ES:NOTHING>
endm
$cend macro
$gen <p1 ENDS>
endm
$$cseg = 1
endif
endm

CODESEG macro p1
ifnb <p1>
$cseg p1&_TEXT
else
$result macro p2
$cseg p2&&_TEXT
endm
$result %@fileName
purge $result
endif
endm

$dseg macro p1
if $$dseg
$err <already have DATASEG>
else
$gen <DGROUP GROUP p1>
$dbeg macro
$gen <p1 SEGMENT WORD PUBLIC 'DATA'>
$gen < ASSUME DS:DGROUP>
endm
$dass macro
$gen < ASSUME DS:DGROUP, ES:NOTHING>
endm
$dend macro
$gen <p1 ENDS>
endm
$$dseg = 1
endif
endm

DATASEG macro p1
ifnb <p1>
$dseg p1
else
$dseg _DATA
endif
endm[/code]
В следующих потомках MASM'a(6+) этот макрос уже прошит в коде компилятора, как директива, т.к. ничего подобного ввиде файла нет.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
07.06.2012, 20:07
общий
Приведенный макрос, к сожалению, мне не очень понятен, т. к. в ассемблере не то чтобы совсем новичок, но где-то на среднем уровне. Но основную мысль, кажется уловил. Получается, MASM как бы "экономит" на выравнивании, за счет чего программа получается короче, так?
давно
Старший Модератор
31795
6196
07.06.2012, 21:06
общий
Цитата: 335419
Получается, MASM как бы "экономит" на выравнивании

Скорее всего, что так, но наверное причина была другая:емкость носителей информации был маленькой, и нужно было поместить как можно больше информации в одном "метре". Потом количество "метров" стало не актуальным, но традиция осталась.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
07.06.2012, 21:32
общий
Ясно. Значит в MASMе тогда буду использовать традиционную запись. Большое Вам спасибо, Константин Николаевич, за такой тщательный разбор моего вопроса. А над статьей, куда Вы дали ссылку, я еще "помедитирую"
давно
Старший Модератор
31795
6196
07.06.2012, 21:51
общий
07.06.2012, 21:52
Цитата: 335419
Приведенный макрос, к сожалению, мне не очень понятен,

Выложил весь макрос препроцессора:
[code h=200];***************
; EXTENDA.INC
; Clipper Extend System Assembler Macros.
; Author..: Dennis L. Dias
; Date....: 11/28/87
.XLIST
;.LALL

$gen macro p1
p1
endm

$err macro m
if2
.err
%out (m)
endif
endm

SES macro p1, p2
$gen < MOV WORD PTR p2[2], ES>
$gen < MOV WORD PTR p2, p1>
endm

SDS macro p1, p2
$gen < MOV WORD PTR p2[2], DS>
$gen < MOV WORD PTR p2, p1>
endm

DOSREQ macro p1
$gen < MOV AH, p1>
$gen < INT 021H>
endm

$define macro p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14
$gen <p1 EQU p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14>
endm

$define PCOUNT <<[WORD PTR [BP - 2]]>>
$define OFFPART <<WORD PTR>>
$define SEGPART <<WORD PTR [2]>>
$define LSW <<WORD PTR>>
$define MSW <<WORD PTR [2]>>

$$lev = 0
$$stat = 0
$$work = 0
$$cseg = 0
$$dseg = 0

CLextern macro p1
irp $$item, <p1>
$x_&&$$item
endm
endm

$define $$UNDEF 0
$define $$CHARACTER 1
$define $$NUMERIC 2
$define $$LOGICAL 4
$define $$DATE 8
$define $$ALIAS 16
$define $$MPTR 32
$define $$MEMO 65
$define $$WORD 128
$define $$ARRAY 512

CLextern <far _parinfo, far _parinfa, far _parc, far _parcsiz, far _parclen>
CLextern <far _parni, far _parnl, far _parnd, far _parl, far _pards>
CLextern <far _retc, far _retclen, far _retni, far _retnl>
CLextern <far _retnd, far _retl, far _retds, far _ret>

$cass macro
endm

$dass macro
endm

$cseg macro p1
if $$cseg
$err <already have CODESEG>
else
$cbeg macro
$gen <p1 SEGMENT BYTE PUBLIC 'CODE'>
endm
$cass macro
$gen < ASSUME CS:&p1, DS:NOTHING, ES:NOTHING>
endm
$cend macro
$gen <p1 ENDS>
endm
$$cseg = 1
endif
endm

CODESEG macro p1
ifnb <p1>
$cseg p1&_TEXT
else
$result macro p2
$cseg p2&&_TEXT
endm
$result %@fileName
purge $result
endif
endm

$dseg macro p1
if $$dseg
$err <already have DATASEG>
else
$gen <DGROUP GROUP p1>
$dbeg macro
$gen <p1 SEGMENT WORD PUBLIC 'DATA'>
$gen < ASSUME DS:DGROUP>
endm
$dass macro
$gen < ASSUME DS:DGROUP, ES:NOTHING>
endm
$dend macro
$gen <p1 ENDS>
endm
$$dseg = 1
endif
endm

DATASEG macro p1
ifnb <p1>
$dseg p1
else
$dseg _DATA
endif
endm

$static macro
if $$dseg EQ 0
$err <STATIC w/o DATASEG>
else
if $$lev EQ 3
$err <STATIC within CLfunc must precede CLcode>
else
if $$stat EQ 0
$dbeg
$$stat = 1
endif
endif
endif
endm

$endstatic macro
if $$stat
$dend
$$stat = 0
endif
endm

CLstatic macro p1
$static
ifb <p1>
else
irp $$item, <p1>
$s_&&$$item
endm
endif
endm

$s_byte macro p1, p2
$gen <p1&_BYTE$ = 1>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
ifnb <p2>
$gen <_&&$$item DB p2>
else
$gen <_&&$$item DB 0>
endif
else
ifnb <p2>
$gen <$$item DB p2>
else
$gen <$$item DB 0>
endif
endif
endm
endm

$s_len macro p1, p2
irp $$item, <p2>
ifdef $$item&&_PUBLIC$
$gen <p1 EQU $-_&&$$item>
else
$gen <p1 EQU $-&&$$item>
endif
endm
endm

$s_int macro p1, p2
$gen <p1&_BYTE$ = 2>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
ifnb <p2>
$gen <_&&$$item DW p2>
else
$gen <_&&$$item DW 0>
endif
else
ifnb <p2>
$gen <$$item DW p2>
else
$gen <$$item DW 0>
endif
endif
endm
endm

$s_log macro p1, p2
$s_int p1, <p2>
endm

$s_long macro p1, p2
$gen <p1&_BYTE$ = 4>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
ifnb <p2>
$gen <_&&$$item DD p2>
else
$gen <_&&$$item DD 0>
endif
else
ifnb <p2>
$gen <$$item DD p2>
else
$gen <$$item DD 0>
endif
endif
endm
endm

$s_double macro p1, p2
$gen <p1&_BYTE$ = 8>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
ifnb <p2>
$gen <_&&$$item DQ p2>
else
$gen <_&&$$item DQ 0>
endif
else
ifnb <p2>
$gen <$$item DQ p2>
else
$gen <$$item DQ 0>
endif
endif
endm
endm

$s_cptr macro p1, p2
$gen <p1&_BYTE$ = 4>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
ifnb <p2>
$gen <_&&$$item DD p2>
else
$gen <_&&$$item DD 0>
endif
else
ifnb <p2>
$gen <$$item DD p2>
else
$gen <$$item DD 0>
endif
endif
endm
$gen <p1&_OFF EQU WORD PTR p1>
$gen <p1&_SEG EQU WORD PTR p1[2]>
$gen <p1&_OFF_BYTE$ = 2>
$gen <p1&_SEG_BYTE$ = 2>
endm

$s_string macro p1, p2
$gen <p1&_BYTE$ = 1>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
ifnb <p2>
$gen <_&&$$item DB p2,0>
else
$gen <_&&$$item DB 0>
endif
else
ifnb <p2>
$gen <$$item DB p2,0>
else
$gen <$$item DB 0>
endif
endif
endm
endm

WORKFUNCS macro
if $$lev
$err <WORKFUNCS within CLfunc/CLret>
else
if $$stat
$endstatic
endif
if $$cseg EQ 0
CODESEG
endif
if $$work EQ 0
$cbeg
$cass
$dass
$$work = 1
endif
endif
endm

ENDWORK macro
if $$work
$cend
$$work = 0
endif
endm

$func macro p1
if $$stat
$endstatic
endif
if $$work
ENDWORK
endif
if $$cseg EQ 0
CODESEG
endif
if $$lev
$err <nested CLfunc>
else
$$lev = 2
$entry macro
$gen <p1 PROC FAR>
endm
$$pb = 10
$$tb = 2
$exit macro
$gen <p1 ENDP>
endm
endif
endm

CLfunc macro p1, p2, p3
$&p1
$func p2
$define $$pl <<p3>>
ifnb <p3>
$$lev = 2
irp $$item, <p3>
$&&$$item
endm
endif
endm

$temp macro
if ($$lev GE 1) AND ($$lev LE 2)
$$lev = 2
else
$err <CLlocal w/o CLfunc>
endif
endm

CLlocal macro p1
$temp
irp $$item, <p1>
$&&$$item
endm
endm

CLcode macro
if ($$lev GE 1) AND ($$lev LE 2)
$cbeg
$cass
$dass
$entry
$gen < PUSH BP>
$gen < PUSH SI>
$gen < PUSH DI>
$gen < MOV BP, SP>
if $$lev EQ 2
$result macro p4
$gen < SUB SP, p4>
endm
$result %$$tb
purge $result
$getparam %$$pl
endif
purge $entry
$$lev = 3
else
$err <CLcode w/o CLfunc>
endif
endm

$getparam macro p1
ifb <p1>
exitm
endif
Ccall _parinfo <0>
$gen < MOV PCOUNT, AX>
$gen < XOR AX, AX>
irp $$item, <p1>
$gen < INC AX>
$gen < PUSH AX>
$p_&&$$item
$gen < POP AX>
endm
endm

$chktype macro p1
$gen < PUSH AX>
Ccall _parinfo <AX>
$gen < TEST AX, p1>
$gen < POP AX>
endm

$p_char macro p1
LOCAL noparam
$gen < MOV WORD PTR p1, 0>
$gen < MOV WORD PTR p1[2], 0>
$gen < CMP AX, PCOUNT>
$gen < JA noparam>
$chktype $$CHARACTER
$gen < JZ noparam>
Ccall _parc <AX>
$gen < MOV WORD PTR p1, AX>
$gen < MOV WORD PTR p1[2], DX>
noparam:
endm

$p_int macro p1
LOCAL noparam
$gen < MOV p1, 0>
$gen < CMP AX, PCOUNT>
$gen < JA noparam>
$chktype $$NUMERIC
$gen < JZ noparam>
Ccall _parni <AX>
$gen < MOV p1, AX>
noparam:
endm

$p_long macro p1
LOCAL noparam
$gen < MOV WORD PTR p1, 0>
$gen < MOV WORD PTR p1[2], 0>
$gen < CMP AX, PCOUNT>
$gen < JA noparam>
$chktype $$NUMERIC
$gen < JZ noparam>
Ccall _parnl <AX>
$gen < MOV WORD PTR p1, AX>
$gen < MOV WORD PTR p1[2], DX>
noparam:
endm

$p_double macro p1
LOCAL noparam
$gen < MOV WORD PTR p1, 0>
$gen < MOV WORD PTR p1[2], 0>
$gen < MOV WORD PTR p1[4], 0>
$gen < MOV WORD PTR p1[6], 0>
$gen < CMP AX, PCOUNT>
$gen < JA noparam>
$chktype $$NUMERIC
$gen < JZ noparam>
Ccall _parnd <AX>
$gen < PUSH ES>
$gen < MOV ES, DX>
$gen < MOV BX, AX>
$gen < MOV AX, ES:[BX]>
$gen < MOV WORD PTR p1, AX>
$gen < MOV AX, ES:[BX + 2]>
$gen < MOV WORD PTR p1[2], AX>
$gen < MOV AX, ES:[BX + 4]>
$gen < MOV WORD PTR p1[4], AX>
$gen < MOV AX, ES:[BX + 6]>
$gen < MOV WORD PTR p1[6], AX>
$gen < POP ES>
noparam:
endm

$p_log macro p1
LOCAL noparam
$gen < MOV p1, 0>
$gen < CMP AX, PCOUNT>
$gen < JA noparam>
$chktype $$LOGICAL
$gen < JZ noparam>
Ccall _parnl <AX>
$gen < MOV p1, AX>
noparam:
endm

$p_date macro p1
LOCAL noparam
$gen < MOV WORD PTR p1, 0>
$gen < MOV WORD PTR p1[2], 0>
$gen < CMP AX, PCOUNT>
$gen < JA noparam>
$chktype $$DATE
$gen < JZ noparam>
Ccall _pards <AX>
$gen < MOV WORD PTR p1, AX>
$gen < MOV WORD PTR p1[2], DX>
noparam:
endm

TESTNUL macro p1
if (p1&_BYTE$) EQ 4
$gen < PUSH AX>
$gen < MOV AX, WORD PTR p1>
$gen < OR AX, WORD PTR p1[2]>
$gen < POP AX>
else
if (p1&_BYTE$) EQ 2
$gen < TEST p1, 0FFFFH>
else
if (p1&_BYTE$) EQ 1
$gen < TEST p1, 0FFH>
else
$gen < PUSH AX>
$gen < MOV AX, WORD PTR p1>
$gen < OR AX, WORD PTR p1[2]>
$gen < OR AX, WORD PTR p1[4]>
$gen < OR AX, WORD PTR p1[6]>
$gen < POP AX>
endif
endif
endif
endm

$treg macro p1
irp $$reg, <AX, BX, CX, DX, SI, DI, CS, DS, ES, SS, BP, SP>
ifidni <p1>, <$$reg>
$$isreg = 1
exitm
endif
endm
endm

$putparam macro p1,p2
$$q = 0
irp $$item, <p1>
$$q = $$q + 1
if $$q EQ p2
$$isreg = 0
$treg <$$item>
if $$isreg
$$pval = $$pval + 2
$gen < PUSH $$item>
else
ifdef $$item
if ($$item&&_BYTE$) EQ 4
$$pval = $$pval + 4
$gen < PUSH WORD PTR $$item[2]>
$gen < PUSH WORD PTR $$item>
else
if ($$item&&_BYTE$) EQ 2
$$pval = $$pval + 2
$gen < PUSH $$item>
else
if ($$item&&_BYTE$) EQ 1
$$pval = $$pval + 2
$gen < PUSH AX>
$gen < MOV AL, $$item>
$gen < MOV AH, 0>
$gen < PUSH BP>
$gen < MOV BP, SP>
$gen < XCHG AX, [BP + 2]>
$gen < POP BP>
else
$$pval = $$pval + 8
$gen < PUSH WORD PTR $$item[6]>
$gen < PUSH WORD PTR $$item[4]>
$gen < PUSH WORD PTR $$item[2]>
$gen < PUSH WORD PTR $$item>
endif
endif
endif
else
$$pval = $$pval + 2
$gen < PUSH AX>
$gen < MOV AX, $$item>
$gen < PUSH BP>
$gen < MOV BP, SP>
$gen < XCHG AX, [BP + 2]>
$gen < POP BP>
endif
endif
exitm
endif
endm
endm

Ccall macro p1,p2
$$pval = 0
ifnb <p2>
$$param_count = 0
irp $$item, <p2>
$$param_count = $$param_count + 1
endm
$$param = $$param_count
rept $$param_count
$putparam <p2>,%$$param
$$param = $$param - 1
endm
endif
$gen < CALL FAR PTR p1>
if $$pval
$gen < ADD SP,$$pval>
endif
endm

CLret macro p1,p2
if $$lev EQ 3
ifnb <p1>
$$isreg = 0
$treg p1
if $$isreg
ifnb <p2>
if $$rb NE 4
$err <Function return mismatch>
else
Ccall $$rf <p2, p1>
endif
else
if ($$rb LT 1) OR ($$rb GT 2)
$err <Function return mismatch>
else
Ccall $$rf <p1>
endif
endif
else
if (p1&_BYTE$) NE $$rb
$err <Function return mismatch>
else
Ccall $$rf <p1>
endif
endif
else
if $$rb NE 0
$err <Function return mismatch>
else
Ccall $$rf
endif
endif
if $$tb
$result macro p4
$gen < ADD SP, p4>
endm
$result %$$tb
purge $result
endif
$gen < POP DI>
$gen < POP SI>
$gen < POP BP>
$gen < RET>
$exit
purge $exit
$cend
else
$err <Return w/o CLfunc/CLcode>
endif
$$lev = 0
endm

$decl macro p1, p2, p3
if $$lev EQ 1
$result macro p4
$gen <p1 EQU [p3 PTR [BP + p4]]>
endm
$result %$$pb
purge $result
$$pb = $$pb + p2
else
if $$lev EQ 2
$$tb = $$tb + p2
$result macro p4
$gen <p1 EQU [p3 PTR [BP - p4]]>
endm
$result %$$tb
purge $result
else
$err <decl w/o CLfunc>
endif
endif
ifidni <p3>, <BYTE>
$gen <p1&_BYTE$ = 1>
else
$gen <p1&_BYTE$ = p2>
endif
endm

$void macro
$$rb = 0
$define $$rf <<_ret>>
endm

$char macro p1
ifnb <p1>
$decl p1, 4, DWORD
else
$$rb = 4
$define $$rf <<_retc>>
endif
endm

$int macro p1
ifnb <p1>
$decl p1, 2, WORD
else
$$rb = 2
$define $$rf <<_retni>>
endif
endm

$long macro p1
ifnb <p1>
$decl p1, 4, DWORD
else
$$rb = 4
$define $$rf <<_retnl>>
endif
endm

$double macro p1
ifnb <p1>
$decl p1, 8, QWORD
else
$$rb = 8
$define $$rf <<_retnd>>
endif
endm

$log macro p1
ifnb <p1>
$decl p1, 2, WORD
else
$$rb = 2
$define $$rf <<_retl>>
endif
endm

$date macro p1
ifnb <p1>
$decl p1, 4, DWORD
else
$$rb = 4
$define $$rf <<_retds>>
endif
endm

CLpublic macro p1
irp $$item, <p1>
$gen < PUBLIC $$item>
endm
endm

Cglobal macro p1
irp $$item, <p1>
$gen < PUBLIC _&&$$item>
$gen <$$item EQU _&&$$item>
$gen <$$item&&_PUBLIC$ = 1>
endm
endm

CLlabel macro p1
irp $$item, <p1>
$l_&&$$item
endm
endm

$l_byte macro p1
$gen <p1&_BYTE$ = 1>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
$gen <_&&$$item LABEL BYTE>
else
$gen <$$item LABEL BYTE>
endif
endm
endm

$l_string macro p1
$l_byte p1
endm

$l_int macro p1
$gen <p1&_BYTE$ = 2>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
$gen <_&&$$item LABEL WORD>
else
$gen <$$item LABEL WORD>
endif
endm
endm

$l_log macro p1
$l_int p1
endm

$l_long macro p1
$gen <p1&_BYTE$ = 4>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
$gen <_&&$$item LABEL DWORD>
else
$gen <$$item LABEL DWORD>
endif
endm
endm

$l_double macro p1
$gen <p1&_BYTE$ = 8>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
$gen <_&&$$item LABEL QWORD>
else
$gen <$$item LABEL QWORD>
endif
endm
endm

$l_cptr macro p1
$gen <p1&_BYTE$ = 4>
irp $$item, <p1>
ifdef $$item&&_PUBLIC$
$gen <_&&$$item LABEL DWORD>
else
$gen <$$item LABEL DWORD>
endif
endm
$gen <p1&_OFF EQU WORD PTR p1>
$gen <p1&_SEG EQU WORD PTR p1[2]>
$gen <p1&_OFF_BYTE$ = 2>
$gen <p1&_SEG_BYTE$ = 2>
endm

$import macro p1, p2
if $$stat
$dend
endif
if $$lev EQ 3
$cend
endif
$gen < EXTRN _&p1:p2>
$gen <p1 EQU _&p1>
if $$stat
$dbeg
endif
if $$lev EQ 3
$cbeg
endif
endm

$x_byte macro p1
$gen <p1&_BYTE$ = 2>
$import p1 WORD
endm

$x_int macro p1
$gen <p1&_BYTE$ = 2>
$import p1 WORD
endm

$x_log macro p1
$x_int p1
endm

$x_long macro p1
$gen <p1&_BYTE$ = 4>
$import p1 DWORD
endm

$x_double macro p1
$gen <p1&_BYTE$ = 8>
$import p1 QWORD
endm

$x_cptr macro p1
$gen <p1&_BYTE$ = 4>
$import p1 DWORD
endm

$x_far macro p1
$import p1 FAR
endm
.LIST[/code]
%out (m) - это встроенная функция компилятора:вывод сообщения на экран.

Макросы очень мощный инструмент в руках программистов.
K примеру:
[code h=200] 154 0000 Matrix label byte
155 = 0001 i = 1
156 rept N*N
157 db i
158 i = i+1
159 endm
1 160 0000 01 db i
1 161 0001 02 db i
1 162 0002 03 db i
1 163 0003 04 db i
1 164 0004 05 db i
1 165 0005 06 db i
1 166 0006 07 db i
1 167 0007 08 db i
1 168 0008 09 db i
1 169 0009 0A db i
1 170 000A 0B db i
1 171 000B 0C db i
1 172 000C 0D db i
1 173 000D 0E db i
1 174 000E 0F db i
1 175 000F 10 db i[/code]
Строчки 154 - 159 макрос, а 160 - 175 результат его работы, по адресам 0х0000 - 0х000F. Если N не 4, а к примеру 100, представляете, сколько нужно было бы стучать по клавишам бедному программисту.

К примеру в TASM есть макрос CALL, слышали о таком:
CALL Name, data1, data2
Попробуйте поработать с ним.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
08.06.2012, 12:22
общий
это ответ
Здравствуйте, Антон!

Проблема связана с тем, как разработчики компиляторов MASM и TASM смотрят на упрощенные директивы определения сегментов. Оба компилятора одинаково генерируют служебную информацию о сегментах в том числе и о выравниваниии(masm,tasm соответственно):




Но по разному генерируют код:



Это видно по адресам 0х0000(В8 хх хх) и 0х0007(ВА хх хх).
MASM совмещает сегменты данных и кода учитывает выравнивание и сегмент данных начинается с ненулевой позиции текущего параграфа, тем самым сокращается длина сгенерированого кода. Полная противоположность TASM, сегмент всегда выравнивается на начало параграфа.

Удачи!
5
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа