Ошибка работы с памятью

Тема в разделе "WASM.ASSEMBLER", создана пользователем Xerx, 17 фев 2005.

  1. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    Здравствуйте! Обращаюсь к вам с просьбой помочь найти ошибку в переносе кода из C++ на Asm. У меня возникли проблемы с выделением памяти и дальнейшем ее использовании.



    Пример такой (удалил все лишнее, компилировал в TC 3.0, работает):
    Код (Text):
    1.  
    2. #include "conio.h"
    3. #include "dos.h"
    4.  
    5. typedef unsigned char byte;
    6. typedef unsigned int word;
    7.  
    8. const
    9.  word ScrSeg = 0xA000;
    10.  byte gMode = 0x13;
    11.  byte tMode = 0x3;
    12.  
    13.  int InitScr(word &VSS) {
    14.   if (VSS == 0) {
    15.     if (_dos_allocmem(4000, &VSS) != 0)
    16.         return 1;
    17.     else
    18.         return 0;
    19.   } else
    20.     return -1;
    21.  }
    22.  
    23.  void DoneScr(word &VSS) {
    24.   if (VSS != 0)
    25.    _dos_freemem(VSS);
    26.  }
    27.  
    28.  void Flip(word D, word S) {
    29.   asm {
    30.    push ds
    31.    mov ax, [D]
    32.    mov es, ax
    33.    mov ax, [S]
    34.    mov ds, ax
    35.    xor si, si
    36.    xor di, di
    37.    mov cx, 16000
    38.    db 0xF3, 0x66, 0xA5
    39.    pop ds
    40.   }
    41.  }
    42.  
    43.  void Clear(word Dest, byte Color) {
    44.   asm {
    45.    mov cx, 16000
    46.    mov es, [Dest]
    47.    xor di, di
    48.    mov al, [Color]
    49.    mov ah, al
    50.    mov dx, ax
    51.    db 0x66, 0xC1, 0xE0, 0x10
    52.    mov ax, dx
    53.    db 0xF3, 0x66, 0xAB
    54.   }
    55.  }
    56.  
    57.  void SetMode(byte Mode) {
    58.   asm {
    59.    xor ah, ah
    60.    mov al, [Mode]
    61.    int 0x10
    62.   }
    63.  }
    64.  
    65. // Example
    66.  
    67. word VSS;
    68.  
    69. void main() {
    70.  SetMode(gMode);
    71.  InitScr(VSS);
    72.  Clear(VSS, 90);
    73.  Flip(ScrSeg, VSS);
    74.  while (!kbhit());
    75.  DoneScr(VSS);
    76.  SetMode(tMode);
    77.  return;
    78. }
    79.  




    А перенос выглядит так (упростил почти до минимума, компилировал в TASM 5.0, соответственно не работает):
    Код (Text):
    1.  
    2. model small
    3.  
    4. stack   8h
    5.  
    6. .const
    7.     ScrSeg  dw  0A000h
    8.     gMode   db  13h
    9.     tMode   db  3h
    10.  
    11. .data
    12.     VSS dw  (0)
    13. .code
    14.  
    15. StdExit proc far
    16.     mov ax, 4C00h
    17.     int 21h
    18. StdExit endp
    19.  
    20. WaitAnyKey proc far
    21.     mov ah, 8h
    22.     int 21h
    23.     ret
    24. WaitAnyKey endp
    25.  
    26. main:
    27.     ; ВЫДЕЛЕНИЕ ПАМЯТИ (InitScr)
    28.     mov bx, 4000
    29.     mov ah, 48h
    30.     int 21h         ; <- вот тут все и накрывается
    31.     jnc AllOk
    32.     call    StdExit
    33. AllOk:
    34.     mov VSS,    ax
    35.  
    36.     ; ПЕРЕКЛЮЧЕНИЕ НА ГРАФИКУ (SetMode)
    37.     mov al, 13h
    38.     xor ah, ah
    39.     int 10h
    40.  
    41.     ; ЗАЛИВКА ЭКРАНА ЦВЕТОМ (Clear)
    42.     mov cx, 16000
    43.     mov ax, VSS
    44.     mov es, ax
    45.     xor di, di
    46.     mov al, 90
    47.     mov ah, al
    48.     mov dx, ax
    49.     db 66h, 0C1h, 0E0h, 10h ; mov shl eax,16
    50.     mov ax, dx
    51.     db 0F3h, 66h, 0ABh  ; rep stosd
    52.  
    53.     ; КОПИРОВАНИЕ ИЗ ПАМЯТИ В ЭКРАННЫЙ БУФЕР (Flip)
    54.     push    ds
    55.     mov ax, ScrSeg
    56.     mov es, ax
    57.     mov ax, VSS
    58.     mov ds, ax
    59.     xor si, si
    60.     xor di, di
    61.     mov cx, 16000
    62.     db 0F3h, 66h, 0A5h  ; rep movsd
    63.     pop ds
    64.  
    65.     ; ОЖИДАНИЕ НАЖАТИЯ КЛАВИШИ (a la kbhit)
    66.     call    WaitAnyKey
    67.  
    68.     ; ПЕРЕКЛЮЧЕНИЕ В ТЕКСТОВЫЙ РЕЖИМ (SetMode)
    69.     mov al, 3h
    70.     xor ah, ah
    71.     int 10h
    72.  
    73.     ; ОСВОБОЖДЕНИЕ ЗАНЯТОЙ ПАМЯТИ (DoneScr)
    74.     mov ax, VSS
    75.     mov es, ax
    76.     mov ah, 49h
    77.     int 21h
    78.  
    79.     ; КОРРЕКТНОЕ ЗАВЕРШЕНИЕ РАБОТЫ
    80.     call    StdExit
    81. end main
    82.  




    Мне не столь вашет сам код, сколько то, что он не работает. При выделении памяти получаю (cf=1, ax=8, bx=7). Получается, что памяти не хватает и я могу использовать только 112 байт!? Но мне нужно почти 64Кб. Что же делать? Объясните ошибку или подкиньте идейку...



    P.S. Заливка (Clear) при замене VSS на ScrSeg также не хочет нормально работать: недобор 8 пикселей в самом конце. Но ПОЧЕМУ все работает в TC и BP (первоисточник я писал в нем давным давно)???



    P.P.S. Я не отрицаю, что мой подход к работе с памятью может быть неправильным, но это единственное, что я нашел. Мне нужно использовать 64000 байт через адрес сегмента и ничего более. Нужно именно динамическое вфыделение памяти, и tmp dd dup (16000) не подойдет. Я откопал, что нужно сначала вернуть неиспользуемую память. Но мне это не сильно помогло...
     
  2. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Код (Text):
    1. main:
    2.     mov ah, 62h
    3.     int 21h
    4.     mov es, bx
    5.     mov bx, 1000h
    6.     mov ah, 4Ah
    7.     int 21h
    8.  
    9.     ; ВЫДЕЛЕНИЕ ПАМЯТИ (InitScr)
    10.     mov bx, 4000
    11.     mov ah, 48h
    12.     int 21h
    13.  
     
  3. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    Отвечаю сам себе:



    model small



    .data

    ; ...

    .code



    ResizeMem proc near

    mov ax, es

    mov bx, SEG end_seg_addr

    sub bx, ax

    mov ah, 04Ah

    int 21h

    jnc short resize_ok

    call StdExit

    resize_ok:

    ret

    ResizeMem endp



    main:

    mov ax, @data ; получение сегмента данных

    mov ds, ax



    call ResizeMem ; освобождение незанятой памяти



    ; выделение памяти



    call StdExit ; корректное завершение работы



    end_seg_addr SEGMENT ; это для выполнения ResizeMem

    end_seg_addr ENDS



    end main