faqs.org.ru

 Главная > Программирование > Другие языки >

FAQ по ассемблеру

From: AutoPost <AutoPost@f96.n5058.z2.fidonet.org>
Date: Mon, 16 Aug 2004 18:40:44 +0400


                            RU.ASM.CHAINIK FAQ
                           редакция от 14.01.2004

    Данный FAQ постится раз в неделю в эхоконференцию RU.ASM.CHAINIK
                Его всегда можно взять на faqserver'е по
                 адресу 2:5058/96.111, топик 'asmfaq'.

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

                              Содержание:

1. Покажите маленькую программку типа 'Hello, world!'
2. А как ее запустить (слинковать, асссемблировать)?
3. А где можно взять tasm и tlink?
4. Что такое PSP?
5. Где хранится командная строка и как ее получить?
6. Как узнать полный путь к запущенной пpогpамме из нее самой?
7. Что такое прерывание и как оно работает?
8. Что такое вектор прерывания?
9. А как можно сгенерировать звук?
10. Что лучше - стандартные или упрощенные директивы определения сегментов?
11.  Для  чего  нужна команда LEA. То же самое может и OFFSET, да и Tasm
заменяет LEA на MOV...OFFSET.
12. Откуда программа узнает адрес сегмента? После компиляции стоит mov ax,1.
13. Как сделать COM с отладочной информацией, понимаемой TD ?
14.  Не  получается!  COM  есть, TDS есть, а TD отладочную информацию не
видит: "Program has no symbol table"
15. Как расчитать количество памяти, необходимое для резидента?
16. Не могу запустить дочернюю задачу функцией 4Bh
17. Не выделяется память по функции 48h
18. Да вроде все есть, почему не выделяет-то?
19. Как сжать блок памяти, занимаемый программой?
20. А что за команда такая rdtsc?
21.  И  еще,  расскажите  русским языком, что такое рекурсия (никогда не
сталкивался!)?
22. Расскажите про сопроцессор, как его использовать?
23. Что делать, если "Relative jump out of range"?
24. (А какие-нибудь ссылки в интернете?) -> смотрите в конце фака
25. А что такое CMOS и как с ней работать?
26. Что делать, если метки одинаковые?
27. Как вывести число в шестнадцатеричном виде?
28. Как слинковать драйвер устройства?
29. Почему программа в отладчике работает, а без отладчика - нет?
30. А как под Windows на ассемблере писать?
last. А как это ... сделать?

----------------------------------------------------------------------------
Q1: Покажите маленькую программку типа 'Hello, world!'
A: Вот пример: Слинковать в com файл (я бы вам пока вообще не рекомендовал
использовать EXE).

..model tiny                     ; модель памяти - делаем com-файл
..code                           ; сегмент кода или пpосто - код
..startup                        ; стаpтовая точка пpогpаммы

        mov ah,09               ; фyнкция N9 - вывод текста на экpан
        mov dx,offset msg       ; в dx заносим адpес сообщения msg
        int 21h                 ; вызов так называемого Сеpвиса Доса
                                ; (в ah для него номеp фyнкции)
        ret                     ; в СОМ-файле так можно завеpшать пpогpамму
                                ; в ЕХЕ - немного сложнее...
msg     db 'Hello, world! $'    ; сообщение (должно оканчиваться на '$')
end                             ; конец файла

----------------------------------------------------------------------------
Q2: А как ее запустить (слинковать, асссемблировать)?
A: Вот так:

tasm hello.asm
tlink /t hello.obj

----------------------------------------------------------------------------
Q3: А где можно взять tasm и tlink?
A: Они вообще-то не freeware, но если очень надо :)
   (http://zigar.narod.ru/faq/minimum.zip)
A2: На факсервере 2:5058/96.111, под именем tasm. (~250 Kb UUE)

----------------------------------------------------------------------------
Q4: Что такое PSP?
A:  PSP  -  структура,  формируемая  для  каждой  запущенной  программы,
содержащая  множество полезной информацию, в частности, командную строку
и  ее длину. Пpи запуске пpогpаммы (как СОМ, так и ЕХЕ) ds и es содеpжат
сегментный адpес PSP. Для COM-файлов он равен еще и cs.

----------------------------------------------------------------------------
Q5: Где хранится командная строка и как ее получить?
A: Командная строка (аргументы, передаваемые запускаемой программе
через командную  строку  DOS (DOS-prompt) и указываемые после имени
программы) хранятся по адресу PSP:[80h] в формате pascal-строки.

Пример:

 C:\DOS> format a:/u/t:80/n:9

Командная строка " a:/u/t:80/n:9", переданная программе format, будет
хранится по указанному адресу в следующем виде:

   db           0Eh," a:/u/t:80/n:9"

+=[x]=Dump=================================
|  ds:0080 0E 20 61 3A 2F 75 2F 74 . a:/u/t
|  ds:0088 3A 38 30 2F 6E 3A 39 0D :80/n:9

----------------------------------------------------------------------------
Q6: Как узнать полный путь к запущенной пpогpамме из нее самой?
A:
        mov     ax,1203h
        int     2Fh              ;получим сегмент данных DOS
        mov     ax,ds
        lds     si,ds:[bp-1Ah]   ;в ds:si - указатель на полный путь


----------------------------------------------------------------------------
Q7: Что такое прерывание и как оно работает?
A:   Прерывание   -  это  именно  прерывание  программы  для  выполнения
какой-либо другой работы.
     Необходимо   pазличать   пpогpаммные   и   аппаpатные   пpеpывания.
Аппаpатные   генеpятся  устpойствами,  а  пpогpаммные  вызываются  самой
пpогpаммой  и являются фактически аналогами вызова подпpогpамм, вызовами
системных   функций   DOS,  напpимеp.  Аппаратные  прерывания  прерывают
программу в необходимый момент, например, по приходу байта от модема, по
движению мыши и т.п.
     Смотрите  первый пример 'Hello, world!', там используется int 21h -
прерывание  номер  21h, которое отвечает за функции ДОС. В ah у нас было
09h - это функция вывода текста на экран, начиная с адреса ds:dx.
---------------------------------------------------------------------------
Q8: Что такое вектор прерывания?
A:  Это  адрес,  по  которому  будет  сделан  переход  в  случае  вызова
соотвествующего  прерывания.  Например, в случае, если в программе стоит
'INT  21h',  адрес перехода берется из ячейки по адресу 0000:21h*4 (по 4
байта на один вектор прерывания).

----------------------------------------------------------------------------
Q9: А как можно сгенерировать звук?
A: Вот так:

            ;
            ; подпрограмма генерации звука
            ; Вход: АX= частота звука в Гц
            ;
 Sound      proc     near
            push     ax        ;сохранить регистры
            push     bx
            push     dx
            mov      bx,ax     ;частота
            mov      ax,34DDh
            mov      dx,12h    ;(dx,ax)=1193181
            cmp      dx,bx     ;если bx < 18Гц, то выход
            jnb      Done      ;чтобы избежать переполнения
            div      bx        ;ax=(dx,ax)/bx
            mov      bx,ax     ;счетчик таймера
            in       al,61h    ;порт РВ
            or       al,3      ;установить биты 0-1
            out      61h,al
            mov      al,00001011b   ;управляющее слово таймера:
                               ;канал 2, режим 3, двоичное слово
            mov      dx,43h
            out      dx,al     ;вывод в регистр режима
            dec      dx
            mov      al,bl
            out      dx,al     ;младший байт счетчика
            mov      al,bh
            out      dx,al     ;старший байт счетчика
 Done:
            pop      dx        ;восстановить регистры
            pop      bx
            pop      ax
            ret
 Sound      endp

Выключение звука:

 No_Sound   proc     near
            push     ax
            in       al,61h    ;порт РВ
            and      al,not 3  ;сброс битов 0-1
            out      61h,al
            pop      ax
            ret
 No_Sound   endp

----------------------------------------------------------------------------
Q10: Что лучше - стандартные или упрощенные директивы определения сегментов?
A: Однозначно проще - упрощенные. Что лучше - решается индивидуально.
   Использование стандартных директив имеет смысл или в педагогических
   целях, или при наличии причин, требующих использования именно стандартных
   директив. Например, необходимость использования специальных имен
   сегментов, специальных атрибутов и особой группировки. Последнее
   опять-таки вовсе не означает, что упрощенные директивы не могут быть
   использованы. Например:

   .MODEL LARGE
          MyGroup       group   MySpecialSeg,$LibTable
          MySpecialSeg  segment word public use16 'DATA'
   ...
          ends
          $LibTable     segment para common use16 'DATA'
          ...
          ends
   .DATA
   .CODE
   end

   Поэтому вполне разумным видится использование упрощенных директив,
   совмещенное (при необходимости) с использованием стандартных.


---------------------------------------------------------------------------
Q11: Для чего нужна команда LEA. То же самое может и OFFSET, да и Tasm заменяет
   LEA на MOV...OFFSET.
A: MOV...OFFSET короче LEA, поэтому в режиме SMART tasm заменяет LEA на MOV
   для тех случаев, когда это возможно:

        lea   di,Array
        mov   di,offset Array

   Но такая замена возможна не всегда:

        lea   di,Array[si+bx.FieldName]

   Логика работы LEA в данном случае эквивалентна такому фрагменту:

        mov   di,offset Array
        add   di,si
        add   di,bx
        add   di,FieldName

   Результат этого фрагмента не может быть вычислен на этапе компиляции
   из-за неизвестных величин, а следовательно, LEA в данном случае не может
   быть заменена командой MOV...OFFSET


---------------------------------------------------------------------------
Q12: mov ax,@data
     mov ds,ax

   Откуда программа узнает адрес сегмента? После компиляции стоит mov ax,1.
   А в отладчике появляется сразу нужный адрес: mov ax,140Fh
   Кто его туда прописывает?

A: Т.к. EXE может быть загружен по различным адресам, вместо явных значений
   cегментов в EXE указаны номера 16-байтных параграфов [0...FFFF] этих
   cегментов, начиная от начала образа EXE. Загрузчик, после считывания образа
   EXE в память, используя информацию в заголовке EXE, находит ссылки на
   явные значения сегментов и прибавляет к значению параграфа, указанное
   непосредственно в команде, реальное значение сегмента, начиная с которого
   загружен EXE.

   Например, образ EXE считан в память, начиная с адреса 140Eh:0 После
   корректировки значений сегментов вместо mov ax,1 получается mov ax,140F

---------------------------------------------------------------------------
Q13: Как сделать COM с отладочной информацией, понимаемой TD ?
A:   comdbg.bat TEST

   tasm /zi %1
   tlink /v %1,%1,,,
   tdstrip -s -c %1.exe

----------------------------------------------------------------------------
Q14: Не получается! COM есть, TDS есть, а TD отладочную информацию не видит:
  "Program has no symbol table"
A: У TDS время меньше, чем у COM - такое бывает в Винде.
   Воспользуйтесь утилитой touch из NWDOS (в MS DOS она похуже)

   touch %1.tds

---------------------------------------------------------------------------
Q15: Как расчитать количество памяти, необходимое для резидента?
A: FirstFreeByteSeg - PspSeg + ((FirstFreeByteOffs+15) div 16)

Resident        macro FirstFreeByteSeg,FirstFreeByteOffs
        mov     dx,FirstFreeByteSeg
        sub     dx,[PspSeg]
        mov     ax,FirstFreeByteOffs
        dec     ax
        shr     ax,4
        inc     ax
        add     dx,ax

        mov     ah,31h
        mov     al,[ErrorLevel]
        int     21h
endm

Resident        seg Install,<offset Install>

---------------------------------------------------------------------------
Q16: Не могу запустить дочернюю задачу функцией 4Bh
Q17: Не выделяется память по функции 48h
A: Нет свободной памяти.

---------------------------------------------------------------------------
Q18: Да вроде все есть, почему не выделяет-то?
A: Да потому что она уже тебе выделена, теперь ее осталось только сжать.

---------------------------------------------------------------------------
Q19: Как сжать блок памяти, занимаемый программой?
A:  Сжимать  ее  следует через функцию DOS 4Ah. Алгоритм тот же, что и у
макроса Resident:

ShrinkMem       macro FreeSeg,FreeOffs
   mov          bx,FreeSeg
   sub          bx,[PspSeg]
   mov          ax,FreeOffs

   dec          ax
   shr          ax,4
   inc          ax

   add          bx,ax
   mov          ah,4Ah
   mov          es,[PspSeg]
   int          21h
endm

ShrinkMem       <seg stack>,<(size stack)+1>
В случае полного/дополнительного ручного объявления сегментов и их особого
упорядочивания необходимо указать имя последнего сегмента.

----------------------------------------------------------------------------
Q20: А что за команда такая rdtsc?
A:  read  tsc - Read Time Stamp Counter. Читает регистр tsc, проще говоря
возвращает  в  edx:eax  количество  тактов  с  момента последнего сброса
процессора.  Опкод  - 0F 31, команда появилась на процессорах Pentium (и
то не на всех.)

---------------------------------------------------------------------------
Q21:. И еще, расскажите русским языком, что такое рекурсия (никогда не
   сталкивался!)?
A: Вызов функцией самой себя.

Q: Примерчик приветствуется.
A: Классический пример - вычисление факториала:

..model farstack small, pascal
   .386
   locals @@
..stack          2048
..code
Factorial       PROC           ; function factorial(@@N:Word):DWord;
   arg          @@N:word       ; begin
   mov          ax,@@N
   cmp          ax,1           ; if (@@N=1) or (@@N=0) then
   ja           @@calc
   mov          ax,1           ;    factorial:=1
   xor          dx,dx
   ret
@@calc:
   dec          ax             ; else
   push         ax
   call         Factorial      ;    factorial := factorial(@@N-1)
   mul          @@N            ;                                  * @@N;
   ret                         ; end;
endp

MAIN            PROC
   .startup
   push         4
   call         Factorial
   .exit
ENDP

end             MAIN


----------------------------------------------------------------------------
Q22: Расскажите про сопроцессор, как его использовать?
A: Вот тебе пример программы с комментариями:

..model tiny
..code
..386                                            ; привычка :)
..387                                            ; использование сопроца
..startup

                         finit                  ; инициализация сопроца
                         fild data1             ; загрузка data1
                         fiadd data2            ; складывание с data2
                         fist _result           ; сохранение результата в
                                                ; _result

                         ret
data1   dw 1
data2   dw 200
_result dw ?

end

Теперь немного теории.
Пример команды:
fild
^^^^
||++
|||
||+-- 'ld' - load, загрузка числа в стек сопроцессора
|+--- 'i' - integer, означает, что работаем с ЦЕЛЫМИ данными (
|           еще варианты - '', то есть fld, например - загрузка вещественного
|           числа в сопроцессор, 'b', т.е. fbld - загрузка BCD числа)
+---- 'f' - обозначает, что это команда сопроцессора

Примеры команд:

fld data1                       ; загрузка вещественного числа из памяти
                                ; по адресу data1 в сопроцессор

fist _result                    ; сохранение числа как целого в память по
                                ; адресу _result (при необходимости оно
округляется -
                                ; это делает сам сопроц)

fistp _result                   ; то же самое, но при сохранении числа оно
                                ; выталкивается из стека сопроца

fsqrt                           ; вычисление квадратного корня из st0, то
                                ; есть аргумент берется из стека, туда же и
                                ; помещается значение корня

fcos, fsin                      ; вычисляет косинус и синус угла, заданного
                                ; в стеке сопроца. Угол должен быть в
                                ; _радианах_.

fsincos                         ; одновременно вычисляет и sin и cos, в
                                ; st0 помещается sin, в st1 - cos.


Вообще для понимания механизма работы возьмите Turbo Debugger:

F10/View/Numeric processor:
Здесь видно, что в стеке сопроца находится число 300 :)

+=[x]=80486 IPTR=54CE3 OPCODE=706 OPTR=54CEE==2=[][]=+
|Valid ST(0) 300                         | im=1 | ie=0 |
|Empty ST(1)                             | dm=1 | de=0 |
|Empty ST(2)                             | zm=1 | ze=0 |
|Empty ST(3)                             | om=1 | oe=0 |
|Empty ST(4)                             | um=1 | ue=0 |
|Empty ST(5)                             | pm=1 | pe=0 |
|Empty ST(6)                             |iem=0 | ir=0 |
|Empty ST(7)                             | pc=3 | cc=0 |
|                                        | rc=0 | st=7 |
|                                        | ic=0 |      |
+xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+======+=====-+

Выполняем:

cs:0107 D9FA           fsqrt

+=[x]=80486 IPTR=54CE7 OPCODE=1FA OPTR=54BE0==2=[][]=+
|Valid ST(0) 17.320508075688773          | im=1 | ie=0 |
|Empty ST(1)                             | dm=1 | de=0 |
|Empty ST(2)                             | zm=1 | ze=0 |
|Empty ST(3)                             | om=1 | oe=0 |
|Empty ST(4)                             | um=1 | ue=0 |
|Empty ST(5)                             | pm=1 | pe=1 |
|Empty ST(6)                             |iem=0 | ir=0 |
|Empty ST(7)                             | pc=3 | cc=0 |
|                                        | rc=0 | st=7 |
|                                        | ic=0 |      |
+xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+======+=====-+

Получили вещественное число в стеке сопроцессора. Сохраним его в памяти
по адресу ds:[110] как целое:

cs:0109 DF1E1001       fistp  word ptr[0110]

Смотрим содержимое:

ds:0110 11 00 FF 16 57 9A A5 1B
        ^^^^^ вон он наш результат :)

----------------------------------------------------------------------------
Q23: Народ, как обойти "Relative jump out of range"?
A: Поставь  директиву  .386  или  даже  больше  -  .586,  напpимеp  - и
наслаждайся...  ;)  А  по умолчанию используется 8086. У него только jmp
short есть.
A2:  А  если  все же пpиспичило писать под пpоцессоp менее 386, то можно
воспользоваться директивой 'jumps':

JUMPS
   ....
   CMP чего надо
   JZ куда надо
   ....
NOJUMPS

И это автоматом постpоит констpукцию, подобную этой:

   CMP чего надо
   JNZ @2
   JMP куда_надо
@2:

     Диpектива   JUMPS   заменяет   все   коpоткие   пеpеходы  на  такую
констpукцию,  в  случае  необходимости.  Поэтому  пользоваться  ей можно
всегда.

----------------------------------------------------------------------------
Q25: А что такое CMOS и как с ней работать?
A: Сейчас под термином CMOS (в рамках компьютерщиков) понимают 64 (уже
говорят, что 128) байт энергонезависимой памяти.
     PC  класса  AT  имеют  питаемые от батарейки часы реального времени
(RTC) и 64 байта постоянной CMOS-памяти.
     Эта  память  содержит  разнообразную информацию, включающую текущие
дату  и  время,  сведения  о конфигурации машины и байт статуса закрытия
системы  (этот  байт  используется  механизмом,  позволяющим  машине  AT
рестартовать   после   выполнения   сброса   процессора,  выводящего  из
защищенного режима).

Работать с ней надо так:

     Чтобы  прочитать  байт  из  CMOS, выполните команду OUT 70H, адрес;
затем  выполните  IN 71H. Чтобы записать байт в CMOS, выполните OUT 70H,
адрес; затем OUT 71H, значение.

Пример:  ;------- прочитать тип установленного твердого диска
         mov     al,12H
         out     70H,al        ;выбрать адрес CMOS 12H
         jmp     $+2           ;требуется небольшая задержка
         in      al,71H        ;теперь в AL тип устройства (0-15)

     Адреса   10H..20H   защищены   контрольной  суммой,  что  позволяет
обнаружить  износ  батарейки или порчу информации в записи конфигурации.
Контрольная сумма - это просто 16-битовая сумма защищаемых байт памяти.
----------------------------------------------------------------------------
Q26:  Тут  такое  дело,  в процедурах у меня часто метки одинаковые, или
вставляю  из  разных  своих  исходников куски, tasm ругается, мол, метки
одинаковые :( Приходится все иправлять... Что сделать-то можно? И вообще
как можно удобно сделать работу с метками?
A: Есть два способа, один простой, другой хитрый :)

Способ  простой:  ставим  в  начале  исходника  locals  @@  и все метки,
начинающиеся  с символов '@@' будут _локальными_, то есть существовать в
пределах одной процедуры и не вызывать конфликта с одинаковыми именами.

Способ  хитрый: у tasm'а есть такой режим работы, при котором существуют
метки  типа  @@,@b,@f (@b и @f соответственно переходят на ближнюю метку
@@  назад, либо вперед), этот режим включается словами 'masm' и 'quirks'
(обязательны обе директивы, иначе работать не будет!). Работает так:
   +------------+
@@:|            |
   +    nop     |
        nop     |
        jmp @b -+
        nop
        jmp @f -+
@@:+    nop     |
   +------------+
----------------------------------------------------------------------------
Q27: А как напечатать число в шестнадцатеричном виде?
A: Можно сделать так:
(результат помещяется в es:di)

byte2hex        proc    near
                push    cx
                mov     cx,2
@@L1:           rol     dl,4
                mov     ax,300fh
                and     al,dl
                aaa
                aad     11h
                stosb
                loop    @@L1
                pop     cx
                ret
byte2hex        endp

word2hex        proc    near
                push    cx
                mov     cx,2
@@L1:           rol     dx,8
                call    byte2hex
                loop    @@L1
                pop     cx
                ret
word2hex        endp

dword2hex       proc    near
                mov     cx,2
@@L1:           rol     edx,16
                call    word2hex
                loop    @@L1
                ret
dword2hex       endp

>Еще:
Преобразует hex-цифру в AL в ASCII-код

Вход:  AL - hex-цифра (00h - 0Fh)
Выход: AL - ASCII - код символа.

cmp     al,10
sbb     al,69h
das

Вот и всё!

После SBB числа 0-9 превращаются в 96h - 9Fh, а числа 0Ah - 0Fh - в 0A1h -
0A6H. Затем DAS вычитает 66h из первой группы чисел, переводя их в 30h - 39h, и
60h из второй группы чисел, переводя их в 41h - 46h

>А вот наиболее очевидный но немного менее быстрый и удобный способ: команда
XLATB. Она помещает в AL байт из таблицы в памяти по адресу ES:BX (или ES:EBX)
со смещением относительно начала таблицы равным AL.

Пример:

Вход:  AL - hex-цифра (00h - 0Fh)
       ES - сегментный адрес таблицы.

Выход: AL - ascii-код символа.

В сегменте кода:

lea   bx,htable
xlatb

В сегменте данных:

htable db "0123456789ABCDEF"

Вот и все.


----------------------------------------------------------------------------
Q28: А как слинковать драйвер устройства (sys, или просто сделать файл с
org0?)
A: Вот так:
tasm driver.asm /m4
tlink driver.obj, driver.sys /t
>               ^ обратите внимание, это самое главное :)

p.s.  Есть  одна  тонкость, на которую я напоролся и имел много проблем.
Тонкость  вот  в  чем.  Если  у  вас  tlink  вызывается через батник, то
слинковать  драйвер вы не сможете, так как батник при разборе параметров
%1  %2  и  т.п. НЕ передаст tlink'у символ запятой, которая здесь играет
решающую  роль.  Так  что линкуйте без батника, либо в нем явно напишите
'tlink driver.obj, driver.bin /t'
----------------------------------------------------------------------------

Q29: Программа выполняется под Turbo Debugger'ом.
     А если её запустить без него, то она виснет/работает неправильно.
Q29: Программа выполняется в операционной системе X.
     А в операционной системе Y - виснет.

A: Возможная причина - программа предполагает, что регистр AA имеет значение
   BB при старте, а инициализация регистров в различных ОС и отладчиках может
   отличаться. Регистры нужно инициализировать самому, не полагаясь на то,
   что при старте в них должно быть что-то записано. Исключение из этого
   правила - сегментные регистры.
----------------------------------------------------------------------------

Q30: А как под Windows на ассемблере писать?
A:   Чтобы писать на ассемблере под Windows. нужен MASM 5 for Windows
(http://win32asm.newmail.ru/), либо TASM 5 с include-файлами.

Пример программы на Tasm'е:

(комментарии -  Anatoly Romashkin)

;tasm32 /m /ml file.asm - если нет tasm32, то можно попpобовать tasm 4.1
;tlink32 /c file.obj

..386
..model flat, stdcall
includelib import32.lib

extrn MessageBoxA:proc
extrn ExitProcess:proc

o equ offset
MB_OK equ 0

..data   ; y меня tasm 4.1 мог глючить, если нет данных
MsgCaption      db 'Qwerty',0
MsgText         db 'Hello, World!',0

..code
start:          call MessageBoxA, 0, o MsgText, o MsgCaption, MB_OK
                call ExitProcess, 0
end start

Пример консольной программы:

;tasm32 /m /ml file.asm - если нет tasm32, то можно попpобовать tasm 4.1
;tlink32 /c /ap file.obj

..386
..model flat, stdcall
includelib import32.lib

extrn ExitProcess:proc
extrn GetStdHandle:proc
extrn WriteFile:proc
extrn ReadFile:proc
extrn SetConsoleMode:proc

o equ offset
STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11
MB_OK equ 0

..data   ; y меня tasm 4.1 мог глючить, если нет данных
MsgText         db 'Hello, World!'
MsgTextLen=$-MsgText
hIn             dd 0
bWritten        dd 0
Buff            db 0
BuffLen=$-Buff

..code
start:
                call    GetStdHandle, STD_OUTPUT_HANDLE
;полyчаю стандаpтный хэндл в eax
                call    WriteFile, eax, o MsgText, MsgTextLen, o bWritten, 0
;пишy в stdout
                call    GetStdHandle, STD_INPUT_HANDLE
                mov     hIn, eax
                call    SetConsoleMode, eax, 0
;yстанавливаю pежим консоли
GetEnter:       call    ReadFile, hIn, o Buff, BuffLen, o bWritten, 0
;читаю с stdin
                cmp     Buff, 0dh ;enter
                jne     GetEnter

                call    ExitProcess, 0

end start

Если не будет pаботать пеpвый ваpиант компиляций указанный в коментаpиях
пpогpаммы или скомпилится с галами, то попpобуйте пpогpаммы откомпилиpовать
вот так:
tasm32 /ml !.asm
tlink32 /Tpe /aa /c !.obj


----------------------------------------------------------------------------
Qlast: А как это ... сделать?
A: Напишите в эху, вам ответят :)

----------------------------------------------------------------------------
Ссылки в интернете:

Сайт Владислава Пирогова (примеры под Windows, куча книг!)
http://asm.shadrinsk.net/

Ассемблер NASM (freeware)
http://nasm.2y.net

Куча ссылок
http://www.ee.mu.oz.au/pgrad/apsh/assembler.htm

Дока по NASM на русском языке (спасибо AsmOS Team)
http://asmdev.narod.ru/asmos/our_files/docs/nasm.win.rar

Interrupt list (хорошее описание прерываний)
http://www.pobox.com/~ralf

Различные базы, дополнения, NG, TechHelp!.
http://www.whitetown.com/ru/ng/
http://www.shortway.to/posohov

Программирование на ASM'е под Windows:
http://win32asm.newmail.ru/

TechHelp! 4.0 RUS
http://zigar.narod.ru/techhelp.zip

Хоpоший тyтоpиал asm под Win32
http://www.wasm.zite.ru/win32asmtutor/files/tutorial/contents.html

Asm под DOS, аpхив pассылки. Полезно, но написано кpиво, поэтомy читать
сложно и неинтеpесно. Но полезно.
http://www.kalashnikoff.ru/Assembler/Issues/index.htm


Бypжyйский сайт, тоже есть тyтоpиалы и пpого пpимеpов. Win32.
http://spiff.tripnet.se/~iczelion/

Список пpеpываний. Понадобится навеpняка. (2.7 mb, на английском)
http://www.cs.cmu.edu/~ralf/interrupt-list/inter61a.zip
....
http://www.cs.cmu.edu/~ralf/interrupt-list/inter61f.zip


Не знаю что там, пpосто URL'ы валялись.
http://win32asm.chat.ru/
http://www.thomasbleeker.nl/exagone/page/int.html
http://sources.fitkursk.ru/articles/art0000037.asp


----------------------------------------------------------------------------
FAQServer                                      2:5058/96.111
----------------------------------------------------------------------------

Все вопросы по содержанию и дополнению FAQ'а отправлять мне -
Alexander Zigar' 2:5058/96

В создании FAQ принимали участие:

 Alexander Zigar'                    2:5058/96
 Anatoly Romashkin                   2:5093/56
 Dima Marakasov                      2:5020/1826.5
 Kirill Barashkin                    2:5080/500.271
 Max Vorobyov                        2:5025/150.24
 Mihail Epihin                       2:5023/29.34
 Roman Perminov                      2:5070/313
 Semen Panevin                       2:5025/121.8
 Victor Petrenko (AsmOS Team)        2:5061/6.40
 Yury Suharev                        2:5023/19.11
 И все те, кого я забыл упомянуть...

 Также спасибо всем подписчикам эх RU.ASM.CHAINIK, TALKS.ASM, PC.CODING и
 им подобных.

Вернуться в раздел "Другие языки" - Обсудить эту статью на Форуме
Главная - Поиск по сайту - О проекте - Форум - Обратная связь

© faqs.org.ru