Линковка в masm32

Тема в разделе "WASM.BEGINNERS", создана пользователем subJ, 22 мар 2009.

  1. subJ

    subJ New Member

    Публикаций:
    0
    Регистрация:
    22 мар 2009
    Сообщения:
    2
    Приступаем к обучению asm. Для того, чтобы уже на первых программах можно было вводить данные и видеть результат, написаны файлы с макрокомандами (io.asm, ioprc.asm). Для нас, дебилов, также заготовлены .exe файлы, которые все это сами линкуют и дают результат. Однако, хочется делать все самому.
    Итак, есть три файла: job.asm - это моя задача, io.asm - файл с макрокомандами (он подключается в первом файле строкой include io.asm) и файл ioprc.asm где описаны процедуры ввода вывода.
    Предварительно готовиться ioprc.obj (что просто), а теперь надо бы линковать job.asm c учетом этого, но у меня не выходит.

    Вот как выглядит .bat файл у преподов (MASM 4.0):
    @echo off
    c:\masm\masm %1,%1,%1 /ic:\masm;
    if errorlevel 1 goto fin
    c:\masm\link %1+c:\masm\ioproc.obj,%1;
    if errorlevel 1 goto fin
    del %1.obj
    %1.exe
    :fin

    Но, по-моему, в masm32 команды типа c:\masm\link %1+c:\masm\ioproc.obj не пройдут?
    ЗЫ. Я не знаю пока ничего о структуре программ на ассемблере. Объясните, как правильно запустить
    (fac прочитан, но в данном вопросе не помог). И да прибудет с вами сила.
     
  2. Blackbeam

    Blackbeam New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2008
    Сообщения:
    960
  3. subJ

    subJ New Member

    Публикаций:
    0
    Регистрация:
    22 мар 2009
    Сообщения:
    2
    Я, наконец, разобрался что к чему и захотелось поделиться (если лишнее - удалите).
    Это пригодится всем тем, кто изучает базовый ассемблер, т.е. сам ассемблер, а не его
    взаимодействие с win32 API. С помощью макроопределний можно вводить и выводить
    информацию как в обычном консольном приложении. Это позволяет заниматься
    только языком в его первозданном виде.

    для этого нужны два файла
    IOPROC.ASM
    Код (Text):
    1. ; Модуль IOPROC:  Процедуры ввода-вывода
    2. public procnl, procoutnum, procflush, procinch, procinint
    3.  
    4. iocode segment
    5.  
    6.        assume cs:iocode
    7.  
    8. ;*********************************************************
    9. ; ВЫВОД НА ЭКРАН
    10. ;*********************************************************
    11.  
    12. ;=========================================================
    13. ; Перевод курсора на новую строку экрана
    14. ; Обращение: call procnl
    15. ; Параметров нет
    16. ;---------------------------------------------------------
    17. procnl proc far
    18.        push dx
    19.        push ax
    20.        mov ah,2
    21.        mov dl,13   ; CR (курсор на начало строки)
    22.        int 21h
    23.        mov dl,10   ; LF (курсор на следующую строку)
    24.        int 21h
    25.        pop ax
    26.        pop dx
    27.        ret
    28. procnl endp
    29.  
    30. ;=========================================================
    31. ; Вывод целого числа-слова со знаком или без знака
    32. ; Обращение: call procoutnum
    33. ; На входе: ах - выводимое число
    34. ;           dh - число со знаком (1) или без знака (0)
    35. ;           dl - ширина поля вывода (>=0)
    36. ;        (если поле больше, чем надо, то слева добавляются пробелы,
    37. ;         если меньше - выводится только число)
    38. ;---------------------------------------------------------
    39.  
    40. procoutnum proc far
    41.       push bp
    42.       mov bp,sp
    43.       push ax
    44.       push dx
    45.       push si
    46.       sub sp,6    ; отвести 6 байтов в стеке под число
    47. ; учет знака
    48.       cmp dh,1    ; вывод со знаком (dh=l) ?
    49.       jne pon0
    50.       cmp ax,0
    51.       jge pon0
    52.       mov dh,2    ; если вывод со знахом и ах<0,
    53.       neg ax      ; то dh:=2, ax:=abs(ax)
    54. pon0: push dx     ; спасти dh (знак) и dl (ширину)
    55. ; запись цифр числа в стек (в обратном порядке)
    56.       xor si,si   ; si - кол-во цифр в числе
    57. ponl: mov dx,0    ; ax -> (dx,ax)
    58.       div cs: ten ; ax=ax div 10; dx=ax mod 10  
    59.       add dl,'0'
    60.       mov byte ptr [bp-8+si], dl ; цифра -> стек
    61.       inc si
    62.       or ax,ax
    63.       jnz ponl    ;  еще не 0
    64. ; запись.минуса, если есть, в стек
    65.       pop dx
    66.       cmp dh,2
    67.       jne pon2
    68.       mov byte ptr [bp-8+si],'-'
    69.       inc si
    70. ; печать пробелов впереди
    71. pon2: mov dh, 0   ; dx - ширина поля вывода
    72.       mov ah ,2   ; функция 02 прерывания 21h
    73. pon21:cmp dx,si
    74.       jle pon3    ; ширина <= длина числа
    75.       push dx
    76.       mov dl,' '
    77.       int 21h
    78.       pop dx
    79.       dec dx
    80.       jmp pon21
    81. ; печать (минуса и) цифр
    82. pon3: dec si
    83.       mov dl,byte ptr [bp-8+si]
    84.       int 21h
    85.       or  si,si
    86.       jnz pon3
    87. ; выход из процедуры
    88.       add sp,6
    89.       pop si
    90.       pop dx
    91.       pop ax
    92.       pop bp
    93.       ret
    94.   ten dw 10
    95. procoutnum endp
    96. ;****************************************************
    97. ; ВВОД С КЛАВИАТУРЫ
    98. ;****************************************************
    99.  
    100. ; буфер ввода с клавиатуры (для работы с функцией OAh)
    101.       maxb db 128    ; макc, размер буфера ввода
    102.       sizeb db 0     ; число введенных символов в буфере
    103.       buf db 128 dup(?)   ; сам буфер ввода
    104.       posb db 0 ; номер послед, считан, символа из buf
    105.  
    106. ;====================================================
    107. ; вспомогательная процедура ввода строки символов
    108. ; (включая Enter) в буфер buf (ввод без приглашения)
    109. ;----------------------------------------------------
    110. readbuf proc near
    111.       push ax
    112.       push dx
    113.       push ds
    114.       mov dx,cs
    115.       mov ds,dx
    116.       lea dx,buf-2   ; ds:dx - адрес buf[-2]
    117.       mov ah,0Ah     ; ввод строки в буфер (включая Enter)
    118.       int 21h
    119.       call procnl    ; курсор на новую строку экрана
    120.       inc cs:sizeb   ; в длине учесть Enter
    121.       mov cs:posb,0  ; сколько символов ухе считано из buf
    122.       pop ds
    123.       pop dx
    124.       pop ax
    125.       ret
    126. readbuf endp
    127. ;====================================================
    128. ; Очистка буфера ввода с клавиатуры
    129. ; Обращение: call prooflush
    130. ; Параметров нет
    131. ;----------------------------------------------------
    132. procflush proc far
    133.      push ax
    134.      mov cs:sizeb,0  ;очистка buf
    135.      mov cs:posb,0
    136.      mov ah,0Ch      ;очистка DOS-буфера
    137.      mov al,0
    138.      int 21h
    139.      pop ax
    140.      ret
    141. procflush endp
    142.  
    143. ;====================================================
    144. ; Ввод символа (с пропуском или без пропуска Enter)
    145. ; Обращение: call procinch
    146. ; На входе: al - Enter пропустить (0) или выдать как символ (1)
    147. ; На выходе: al - введенный символ (ah яе меняется)
    148. ;----------------------------------------------------
    149. procinch proc far
    150.      push bx
    151. princh1:
    152.      mov bl,cs:posb    ; номер последнего считанного символа
    153.      inc bl            ; след. номер
    154.      cmp bl,cs:sizeb   ; на последний символ буфера?
    155.      jb princh2
    156.      jne princh10      ; буфер на считан до конца?
    157.      cmp al,0          ; считывать ли конец строки (Enter)?
    158.      jne princh2
    159. princh10:
    160.      call readbuf      ; доввод в буфер
    161.      jmp princh1       ; повторить
    162. princh2:
    163.      mov cs:posb,bl    ; запомнить номер считываемого символа
    164.      mov bh,0
    165.      mov al,cs:buf[bx-1] ;al:=символ
    166.      pop bx
    167.      ret
    168. procinch endp
    169. ;====================================================
    170. ; Ввод целого числа (со знаком и беэ) размером в слово
    171. ; Обращение: call proclnint
    172. ; На входе: нет
    173. ; На выходе: ах - введенное число
    174. ;----------------------------------------------------
    175. procinint proc far
    176.      push bx
    177.      push cx
    178.      push dx
    179. ; пропуск пробелов и хонцов отрок вначале
    180. prinint1:
    181.      mov al,0
    182.      call procinch    ;al - очередной символ (с пропуском Enter)
    183.      cmp al,' '       ;пробел?
    184.      je prinint1
    185. ; проверка на знак
    186.      mov dx,0         ; dx - вводимое число
    187.      mov cx,0         ; ch = 0 - нет цифры, cl=0 - плюс
    188.      cmp al, '+'
    189.      je prinint2
    190.      cmp al,'-'
    191.      jne prinint3
    192.      mov cl, 1        ; cl = 1 - минус
    193. ; цикл по цифрам
    194. prinint2:
    195.      mov al,1
    196.      call procinch    ; al - очередной символ (Enter - символ)
    197. prinint3:             ; проверка на цифру
    198.      cmp al,'9'
    199.      ja prinint4      ; >'9'?
    200.      sub al,'0'
    201.      jb prinint4      ; <'0'?
    202.      mov ch,1         ;ch = 1 - есть цифра
    203.      mov ah,0
    204.      mov bx,ax        ;bx - цифра как число
    205.      mov ax,dx
    206.      mul cs:prten     ;*10
    207.      jc provfl        ;>FFFFh (dx<>0) -> переполнение
    208.      add ax,bx        ;+ цифра
    209.      jc provfl
    210.      mov dx,ax        ;спасти число в dx
    211.      jmp prinint2     ;к след. символу
    212. ; кончились цифры (число в dx)
    213. prinint4:
    214.      mov ax,dx
    215.      cmp ch,1         ;были цифры?
    216.      jne prnodig
    217.      cmp cl,1         ;был минус?
    218.      jne prinint5
    219.      cmp ax,8000h     ;модуль отриц. числа > 8000h ?
    220.      ja provfl
    221.      neg ax           ;взять с минусом
    222. prinint5:
    223.      pop dx           ;выход
    224.      pop cx
    225.      pop bx
    226.      ret
    227. prten dw 10
    228. ;------------реакция на ошибки при вводе числа
    229. provfl: lea cx,prmsgovfl ; переполнение
    230.      jmp prerr
    231. prnodig:lea cx, prmsgnodig ; нет цифр
    232. prerr: push cs        ;печать сообщения об ошибке
    233.      pop ds           ;ds = cs
    234.      lea dX,prmsg
    235.      mov ah,9         ;outstr
    236.      int 21h
    237.      mov dx,cx
    238.      mov ah,9         ;outstr
    239.      int 21h
    240.      call procnl
    241.      mov ah,4Ch       ; finish
    242.      int 21h
    243. prmsg db 'Ошибка при вводе числа: ','$'
    244. prmsgovfl db 'переполнение','$'
    245. prmsgnodig db 'нет цифры','$'
    246. procinint endp
    247. iocode ends
    248.      end              ; конец модуля ioproc
    и
    IO.ASM
    Код (Text):
    1. .xlist   ;запрет записи этого файла в листинг
    2. ; Файл с макросами ввода-вывода, подключаемый к
    3. ; программе по директиве: include io.asm
    4. ;***********************************************************
    5. ; ОКОНЧАНИЕ СЧЕТА ПРОГРАММЫ
    6. ;***********************************************************
    7.  
    8. ;===========================================================
    9. ; Окончание счета программы
    10. ; обращение: finish
    11. ; на входе: al - код завершения (можно игнорировать)
    12. ;-----------------------------------------------------------
    13. finish macro
    14.        mov ah,4Ch
    15.        int 21h
    16.        endm
    17. ;***********************************************************
    18. ; ВЫВОД НА ЭКРАН (в текстовом режиме)
    19. ;***********************************************************
    20.    
    21. ;===========================================================
    22. ; Переход на новую    строку
    23. ;      обращение:  newline
    24. ;-----------------------------------------------------------
    25. extrn procnl:far
    26. newline macro
    27.        call procnl
    28.        endm
    29. ;===========================================================
    30. ; Вывод символа
    31. ;       обращение: outch с
    32. ;       где с - i8, r8 или m8
    33. ;-----------------------------------------------------------
    34. outch macro c
    35.        push dx
    36.        push ax
    37.        mov dl,c
    38.        mov ah,2
    39.        int 21h
    40.        pop ax
    41.        pop dx
    42.        endm
    43. ;===========================================================
    44. ; Вывод строки символов
    45. ;       обращение: outstr
    46. ;       на входе: ds:dx - начальный адрес строки
    47. ;       (в конце строки д.6. символ $, код 36 (24h))
    48. ;-----------------------------------------------------------
    49. outstr macro
    50.        push ax
    51.        mov ah,9
    52.        int 21h
    53.        pop ax
    54.        endm
    55. ;===========================================================
    56. ; Вывод целого со знаком размером в слово
    57. ; обращение: outint num [,leng]
    58. ; где num - выводимое число: i16, r16, m16
    59. ;     leng - ширина поля вывода: i8, r8, m8 (со значением >=0)
    60. ; Особенности вывода:
    61. ; если поле больше, чем надо, то слева добавляются пробелы,
    62. ; если меньше - выводится только число (целиком);
    63. ; по умолчанию leng = 0
    64. ;-----------------------------------------------------------
    65. extrn procoutnum:far
    66. outint macro num, leng
    67.        outnum <num>,<leng>,1
    68.        endm
    69. ;===========================================================
    70. ; Вывод целого без знака размером в слово
    71. ; обращение:       outword num [,leng]
    72. ;                  num и leng - как в outint
    73. ;-----------------------------------------------------------
    74. outword macro num, leng
    75.         outnum <num>,<leng>,0
    76.         endm
    77. ;-----------------------------------------------------------
    78. ; Вспомогательный макрос проверки написания имени
    79. ; разными (большими и малыми) буквами
    80. ;-----------------------------------------------------------
    81. same macro name,variants,ans
    82.      ans = 0
    83.      irp v,<variants>
    84.      ifidn <name>,<v>
    85.      ans = 1
    86.      exitm
    87.      endif
    88.      endm
    89.      endm
    90. ;-----------------------------------------------------------
    91. ; Вспомогательный макрос для outint (sign=1) и outword (=0)
    92. ;-----------------------------------------------------------
    93. outnum macro num,leng,sign
    94.      local regdx?
    95.      push ax
    96.      push dx
    97.      same <num>,<dx,DX,Dx,dX>,regdx?
    98.      if regdx?    ;;out dx,leng -->
    99.      ifb <leng>   ;;mov al, leng
    100.      mov al,0     ;;xchg ax, dx
    101.      else
    102.      mov al,leng
    103.      endif
    104.      xchg ax,dx
    105.      else         ;;out num, leng (num<>dx)
    106.      ifb <leng>   ;;mov dl, leng
    107.      mov dl,0     ;;movax, num
    108.      else
    109.      mov dl,leng
    110.      endif
    111.      mov ax,num
    112.      endif
    113.      mov dh,sign
    114.      call procoutnum   ;;ax=num, dl=leng, dh=sign
    115.      pop dx
    116.      pop ax
    117.      endm
    118. ;**********************************************************
    119. ; ВВОД С КЛАВИАТУРЫ
    120. ;**********************************************************
    121.  
    122. ;==========================================================
    123. ; Очистка буфера ввода с клавиатуры
    124. ; обращение: flush
    125. ;----------------------------------------------------------
    126. extrn procflush:far
    127.  flush macro
    128.        call procflush
    129.        endm
    130. ;==========================================================
    131. ; Ввод символа (с пропуском концов строк, т. е. Enter)
    132. ; обращение: inch х
    133. ;         где х - r8, m8
    134. ; на выходе: х - введенный символ
    135. ;----------------------------------------------------------
    136. extrn procinch:far
    137.   inch macro x
    138.        local regax?
    139.        same <x>,<ah,AH,Ah,aH>,regax?
    140.        if regax?
    141.        xchg ah,al       ;;x=ah
    142.        mov al,0
    143.        call procinch
    144.        xchg ah,al
    145.        else
    146.        same <x>,<al,AL,Al,aL>,regax?
    147.        if regax?
    148.        mov al,0         ;;x=al
    149.        call procinch
    150.        else
    151.        push ax          ;;x - не ah и не al
    152.        mov al,0
    153.        call procinch
    154.        mov x,al
    155.        pop ax
    156.        endif
    157.        endif
    158.        endm
    159. ;==========================================================
    160. ; Ввод целого числа (со знаком и без) размером в слово
    161. ; обращение: inint х
    162. ;        где х - r16, m16
    163. ; на выходе: х - введенное число
    164. ; особенности ввода:
    165. ;        пропускаются все пробелы и концы строк перед числом;
    166. ;        число должно начинаться с цифры, перед ней возможен знак;
    167. ;        при минусе число вводится как отрицательное;
    168. ;        ввод идет до первой нецифры (в т.ч. до Enter), она глотается;
    169. ;        при ошибке будет печать сообщения и останов программы;
    170. ; ошибки:  "нет цифры" - в числе нет ни одной цифры
    171. ;        "переполнение" - большое по модулю число
    172. ;        (вне отрезка [-32768, +65535])
    173. ;----------------------------------------------------------
    174. extrn procinint:far
    175.   inint macro x
    176.         local regax?
    177.         same <x>,<ax,AX,Ax,aX>,regax?
    178.         if regax?
    179.         call procinint       ;;x=ax
    180.         else
    181.         push ax              ;;x<>ax
    182.         call procinint
    183.         mov x,ax
    184.         pop ax
    185.         endif
    186.         endm
    187. ;==========================================================
    188. ; восстановить запись в листинг:
    189.         .list
    Используя их можно писать простые законченные програмки. Например,
    Вводим число(целое знаковое) X, а выводим
    (2*A - 1234 div (A+B)^2) mod 7

    TESTIO.ASM
    Код (Text):
    1. INCLUDE IO.ASM
    2. data segment
    3.   A  dw ?
    4.   B  db -8
    5.   X  dw ?
    6. data ends
    7. ;-------------------------------
    8. stack segment stack
    9.       db 128 dup (?)
    10. stack ends
    11. ;-------------------------------
    12. code segment
    13.      assume cs:code, ds:data, ss:stack
    14.  
    15. start:
    16.     mov ax, data
    17.     mov ds, ax
    18.     inint A
    19.     mov bx, A
    20.     mov al, B
    21.     cbw
    22.     add ax, bx
    23.     add bx, bx
    24.     imul ax
    25.     mov cx, ax
    26.     mov ax, 1234
    27.     cwd
    28.     idiv cx
    29.     sub bx, ax
    30.     mov ax, bx
    31.     cwd
    32.     mov bx, 7
    33.     idiv bx
    34.     mov X, dx
    35.     outint X
    36.     finish
    37. code ends
    38.      end start
    Поигравшись с компиляторами, мне проще всего оказалась работа
    с этим: http://beleriand.narod.ru/programming.html

    Файл .bat будет примерно такой:
    cls
    echo off
    C:\MASM611\BIN\ML /c E:\WORK\ASM\Tutor\Ch1\MASM\IOPROC.ASM
    C:\MASM611\BIN\ML /c E:\WORK\ASM\Tutor\Ch1\MASM\TESTIO.ASM
    C:\MASM611\BINR\link "E:\WORK\ASM\Tutor\Ch1\MASM\TESTIO.OBJ"+"E:\WORK\ASM\Tutor\Ch1\MASM\IOPROC.OBJ"
    pause

    Может, это кому-то поможет.
     
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.231
    subJ
    Насчет bat-файла посмотри здесь