Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вызов процедуры с передачей параметров через стэк (ассемблер)

10K
16 октября 2007 года
Shalfey
47 / / 10.03.2007
Среда выполнения: 16-разрядная
Задача:
Задан массив А из N = 50 элементов (констант типа WORD).
Определить сумму элементов массива А , для которых биты 2 и 10
не совпадают .

Решение задачи, позитивно оцененное преподавателем:
Код:
data segment
    arr dw  20 dup (0001011000000100b), 5 dup (?),
10 dup (0000000010011110b),     11 dup (0000010000001011b), 4 dup (101001b)
    num_el  dw  50
    sum dw  0
    mask_2  dw  0000000000000100b
    mask_10 dw  0000010000000000b
data ends
code segment
    assume cs:code, ds:data
    start:
        mov     ax, data
        mov ds, ax
        mov cx, num_el
        xor ax, ax
        xor dx, dx
        xor bx, bx
        lea si, arr
    cycle: 
mov ax, [si]
        mov dx, [si]
        mov bx, [si]
        and ax, mask_2
        and dx, mask_10
        shr dx, 8
        cmp ax, dx
        je  equal
        add sum, bx
    equal: 
add si, 2
        loop    cycle
        mov ah, 4Ch
        int 21h
code ends
    end start


Необходимо разработать на языке ассемблера и отладить программу, содержащую главную подпрограмму и вызываемую иэ нее процедуру, которые находятся в отдельных кодовых сегментах разных исходных модулей (файлов). Взаимодействие между ними по данным осуществить путем передачи адресов параметров через стек. Данные и стек определите в отдельных сегментах в исходном модуле, где находится главная подпрограмма. Занесение адресов параметров в стек реализовать в вызывающей последовательности в главной подпрограмме. В вызываемой процедуре осуществить выполнение
индивидуального задания (приведено выше).

Мой вариант реализации:
lb6_1.asm
Код:
data segment
    arr dw  20 dup (1011000000100b), 5 dup (?), 10 dup (10011110b),                     11 dup (10000001011b), 4 dup (101001b)
    num_el  dw  50
    sum dw  0
data ends
stak segment stack
        dw  100 dup (?)
    tos label word
stak ends
code segment
    extrn procedure:far
    assume cs:code, ds:data, ss:stak
    start:
        mov     ax, data
        mov ds, ax
        mov ax, stak
        mov ss, ax
        mov sp, offset tos
        mov ax, offset num_el
        push    ax
        mov ax, offset sum
        push    ax
        mov ax, offset arr
        push    ax
        call    far ptr procedure
        mov ah, 4Ch
        int 21h
code ends
    end start

lb6_2.asm
Код:
code_procedure segment
    public procedure
    mask_2  dw  100b
    mask_10 dw  10000000000b
    summa   dw  0
    assume cs:code_procedure
    procedure proc far
        push    bp
        mov bp, sp
        push    ax
        push    bx
        push    cx
        push    dx
        push    si

        mov si, [bp+10] ; addr num_el
        mov cx, [si]
        mov si, [bp+8]  ; addr sum
        push    word ptr [si]
        pop summa
        mov si, [bp+6]  ; addr arr
    cycle: 
        mov ax, [si]
        mov dx, [si]
        mov bx, [si]
        and ax, mask_2
        and dx, mask_10
        shr dx, 8
        cmp ax, dx
        je  equal
        add summa, bx
    equal: 
        add si, 2
        loop    cycle
        mov si, [bp+8]
        push    summa
        pop word ptr [si]
        pop si
        pop dx
        pop cx
        pop bx
        pop ax
        pop bp
        retf   
    procedure endp
code_procedure ends
    end

Программа успешно ассемблируется с использованием tasm 5. Результат выполнения неверен (должен быть 32А5). Путём отладки в турбо-дебаггере ошибочный фрагмент был найден. Во время входа в процедуру значения mask_2 и mask_10 отличаются от заданных. Всё остальное работает верно. Откуда взялась ошибка и как её исправить?
602
17 октября 2007 года
KPI Student
265 / / 16.12.2006
Я думаю, проблема вот в чем:
Цитата:
 
Код:
code_procedure segment
    public procedure
    mask_2  dw  100b
    mask_10 dw  10000000000b
    summa   dw  0
    assume cs:code_procedure
. . . . .

Т.е. у тебя mask_2 и mask_10 хранится внутри code_procedure segment
Обращаешься ты к ним чезез имя переменной, т.е. через указатель.

Цитата:
and ax, mask_2
and dx, mask_10


имхо, это аналогично такому коду:

 
Код:
and ax, [ offset mask_2]  ; доступ к переменной происходи через ее адрес
and dx, [ offset mask_10]

При этом обращение к переменной должно выглядеть таким образом:
 
Код:
mask_2 = [ code_procedure(сегмент) : ХХХХ(смещение) ]
...
and ax,[code_procedure:XXXX]
...

А компилятор-то по умолчанию обращается вот так! :

 
Код:
mask_2 = [ds:XXXX]
;    В твоем случае ds указывает на data segment, тогда:
mask_2 = [ data(сегмент) : XXXX(смещение) ]
...
and ax,[data:XXXX]

А [data:XXXX] [code_procedure:XXXX] -- это две разные переменные, расположеные по двум разным адресам. Отсюда и ошибка.

Оказывается, при чтении значений mask_* из памяти компилятор по причине отсутствия телепатических возможностей обращается не к тому сегменту, к которому ты хочешь, чтобы он обратился, а к сегменту, указаному в регистре DS.

Мой вариант решения проблемы:

Код:
procedure proc far
. . . (старый код) . . .
[INDENT]mov di,code_procedure ; в di адрес c_p (просто вынес за границы цикла)[/INDENT]cycle:[INDENT]mov ax, [si] ; тут еще данные хранятся в сегменте data
mov dx, [si]
mov bx, [si]
        ; а тут уже в сегменте code_procedure
push ds ; сохраняем адрес data segment в стеке
        ; mov ds,cs или mov ds,cope_procedure -- так нельзя (проверил)
mov ds,di ; так можно (тоже проверил)

and ax, mask_2
and dx, mask_10
        ; code_procedure segment в DS больше не нужен
pop ds
        ;  адрес data segment восстановлен из стека

 . . .  ( дальше старый текст ) . . .
[/INDENT]


Работоспособность не проверял, но думаю, что должно работать, т.к. изменение текста исходной процедуры (той, что одобрена преподавателем:) ) минимальные.

А вот работа со стеком внутри цикла скажется на скорости выполнения программы.

P.S. Пол-шестого. РГЗ по ТЭМЦ рулит!!! :) :) :)
10K
17 октября 2007 года
Shalfey
47 / / 10.03.2007
Как ни странно, результат работы программы всё равно неверен. Абсолютно никаких изменений, та же проблема.
622
17 октября 2007 года
nilbog
507 / / 19.12.2006
вы точно поменяли сегментирование
попробуйте
mov di,code_procedure
mov es,di
and ax,es:mask_2
или там тоже самое используя регистр ds но поменяйте assume тогда
;вообще это то же самое что уже предложили - но раз mask_2 mask_10 заранее знаете не проще ли использовать define
10K
17 октября 2007 года
Shalfey
47 / / 10.03.2007
KPI_Student
Спасибо, Витёк! Я понял, в чём проблема.
nilbog
Огромное спасибо, ваша правка
 
Код:
mov di,code_procedure
mov es,di
and ax,es:mask_2

отлично поправила положение дел. Программа работает правильно.
Спасибо за помощь!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог