Помогите понять, где ошибка
От: Maxim_Solovjev  
Дата: 10.05.03 11:51
Оценка:
Есть программа на асме, компилирую тасм 5.0
Программа должна прочитать через int 13h первый сектор корневого каталога дискеты 3.5'', из которого она берет первую запись о файле, в этой записи находит номер первого кластера, после чего пытается прочесть значение следующего кластера этого файла.

Собственно проблема заключается в следующем:
В случае, если помеченные строки оставить закомментированными, то функция read_lsect (которая читает сектор дискеты, логический номер которого помещен в ax) работает нормально и деления ax на bx (ax=0002h, bx=0024h) проходит нормально.

Если же раскомментировать указанные строки, то дебагер при делении div bx выдаёт "Terminated, error code 256", в случае запуска программы она выдаёт divide overflow

Запускаю под WinXP на Athlon XP 2000+, дискета форматирована стандартно
В чем ошибка и как с этим бороться? Спасибо!



;Чтение FAT таблицы посредством int 13h
;Определяем макроконстанты
;------------------------------------
FNumber equ 19d            ;Количество файлов, обрабатываемых в корневом каталоге
RootDir equ 19d                ;Логический сектор корневого каталога
;------------------------------------
DataSg segment 'DATA'
    buffer db 1024 dup(?)  ;создаем буфер
    clustnum dw ?           ;используется для proc get_clust
    i dw ?               ;используется в циклах    
DataSg ends
;------------------------------------
CodeSg segment 'CODE'
assume CS:CodeSg, DS:DataSg, SS:StackSg
begin:    
    mov ax, DataSg
    mov ds, ax

;    mov ax,RootDir          <<<<<< вот эти строки
;    call read_ls          <<<<<<
    
;    mov ax,[ds:1Ah]       <<<<<<
;    mov clustnum,ax       <<<<<<

    mov ax,2h
    call read_ls
    
    mov ax, 4C00h
    int 21h
;==============================================================================
read_ls proc            ;прочитать логический сектор
                ;номер сектора передаётся через ax

    mov bx,24h              
    div bx                  ;<<<<<<здесь она начинает выдавать ошибку 

    mov ch,al        ;заносим номер цилиндра/дорожки

    cmp dl,12h              ;проверяем "остаток" в dl
    jg bolshe               ;если больше, то идем по метке

    mov dh,0h        ;если меньше или равно головку/сторону 
                ;инициализируем 0h    
    jmp contin
bolshe: 
    sub dl,12h        ;где вычитаем кол-во секторов на дорожке
    mov dh,1h        ;а головку/сторону инициализируем 1h
    inc dl
contin:
    mov cl,dl                         
    call read_sect
    ret    
read_ls endp
;==============================================================================
read_sect proc            ;процедура читает сектор, указанные 
                ;через регистры
                ;dh - номер головки
                ;ch - номер дорожки/цилиндра
                ;cl - номер сектора

        mov ax,seg buffer       ;ES:BX должны указывать на буфер
       mov es,ax               
       mov bx,offset buffer    
       mov dl,0                ;номер накопителя
       mov al,1                ;число секторов для чтения
       mov ah,2                ;номер функции чтения
       int 13h                 
    ret
read_sect endp
;==============================================================================
get_clust proc             ;предварительно в buffer должна храниться FAT
                ;в clustnum содержится номер кластера, значение
                ;для которого необходимо узнать
                ;это условие выполняется посредством сл. 4строк

        mov  ax,clustnum          ;номер кластера в AX
        mov  cx,ax              ;делаем копию
        mov  dx,ax              ;делаем вторую копию
        shr  dx,1               ;делим вторую копию на 2
        add  cx,dx              ;складываем между собой
        add  bx,cx              ;добавляем как смещение
        mov  dx,[bx]            ;получаем 2 байта из этого места
        test ax,1               ;номер кластера нечетный?
        jnz  nechet            ;уход, если да
        and  dx,0000111111111111b    ;получаем номер
        jmp  short cont       ;уход через обработку нечетного
nechet: mov  cl,4              ;подготовка к сдвигу вправо
        shr  dx,cl              ;сдвигаем вниз старшие 12 битов
cont:

    ret
get_clust endp
;==============================================================================
CodeSg ends
;------------------------------------
StackSg segment stack 'STACK'
    db 256 dup(0)
StackSg ends
;------------------------------------
end begin
Re: Помогите понять, где ошибка
От: Алексей Владимирович Миронов Россия  
Дата: 10.05.03 13:35
Оценка:
Здравствуйте, Maxim_Solovjev, Вы писали:

MS>Если же раскомментировать указанные строки, то дебагер при делении div bx выдаёт "Terminated, error code 256", в случае запуска программы она выдаёт divide overflow


Инструкция DIV в Вашем случае ожидает частное в регистровой паре DX:AX:

DIV—Unsigned Divide

Divides (unsigned) the value in the AX register, DX:AX register pair, or EDX:EAX register pair (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers.

Operation

IF OperandSize = 16 (* doubleword/word operation *)
THEN
  temp <- DX:AX / SRC;
  IF temp > FFFFH
  THEN #DE; (* divide error *) ;
ELSE
  AX <- temp;
  DX <- DX:AX MOD SRC;
FI;

Real-Address Mode Exceptions

#DE If the source operand (divisor) is 0. If the quotient is too large for the designated register.


(Цит. по: Intel Architecture Software Developer’s Manual. Volume 2: Instruction Set Reference)

Неизвестно, что находится в момент деления в регистре DX. Получаемое частное может не помещаться в регистре AX, вот процессор и выдает Divide Error.
... << RSDN@Home 1.0 beta 6a >>
Re[2]: Помогите понять, где ошибка
От: Maxim_Solovjev  
Дата: 10.05.03 20:26
Оценка:
Большое спасибо,
проблема решена!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.