Как я могу скопировать данные памяти из указателя в массив ASSEMBY 8086 - PullRequest
1 голос
/ 28 марта 2019

Я работаю над программой на C, которая вызывает функцию сборки, передавая массив в качестве аргумента.В коде ассемблера (для 8086) я могу получить адрес массива в памяти и сохранить адреса в ES:BX, но после этого мне нужно скопировать значения в массив BARCODE, но я не могу найтилюбой способ достижения этого.

Мой код выглядит примерно так:

Ccode:

unsigned char computeControlDigit(char* barCodeASCII);

int main( void ){
char barCodeStr[14]
unsigned char controlDigitCheck;

controlDigitCheck = computeControlDigit(barCodeStr);
}

Код сборки:

_DATA SEGMENT WORD PUBLIC 'DATA'
    BARCODE DB 13 DUP(?)
_DATA ENDS

PUBLIC _computeControlDigit                     
_computeControlDigit PROC FAR
    PUSH BP 
    MOV BP, SP
    PUSH ES
    LES BX, [BP+6]

    ; code to copy from memory to
    ; array and code of operations on the array

    POP ES
    POP BP
    RET
_computeControlDigit ENDP                           
_TEXT ENDS
END

Любая помощьбыло бы очень приятно.

Ответы [ 2 ]

1 голос
/ 28 марта 2019

В модели большой памяти все данные и код имеют значение FAR и должны указываться через соответствующий сегмент.В приведенном ниже коде я загружаю указатель на исходную строку barcodestr в DS: SI и BARCODE в ES: DI .Затем я читаю символ из массива barcodestr с помощью LODSB и сохраняю его в BARCODE с помощью STOSB.Копирование заканчивается, когда достигнут терминатор NUL.

STOSB похоже 1 на выполнение:

mov [ES:DI], al
inc di

LODSB аналогично 1 на выполнение:

mov al, [DS:SI]
inc si

Я не знаю, используете ли вы MASM или TASM в качестве ассемблера, поэтому я предоставляю версию для обоих.Пример кода TASM, который просто копирует завершенную NUL-строку, выглядит следующим образом:

.MODEL LARGE, C

PUBLIC computeControlDigit

_DATA SEGMENT WORD PUBLIC 'DATA'
    BARCODE DB 13 DUP(?)
_DATA ENDS

_TEXT SEGMENT WORD PUBLIC 'TEXT'
ASSUME DS:_DATA, CS:_TEXT

computeControlDigit PROC C FAR
    ARG %%barcodestr:DWORD      ; barcodestr is a FAR pointer (DWORD)
    USES DS, SI, DI             ; Save non-volatile registers

    MOV AX, SEG BARCODE         ; Get segment and offset (FAR PTR) of BARCODE
    MOV ES, AX                  ; into ES:DI
    MOV DI, OFFSET BARCODE

    LDS SI, %%barcodestr        ; Load barcodestr FAR pointer into DS:SI
    JMP %%GETCHAR               ; Get next character

%%NEXTCHAR:
    STOSB                       ; Store character to ES:DI (BARCODE), DI++
%%GETCHAR:
    LODSB                       ; Read character from DS:SI (barcodestr), SI++
    TEST AL, AL                 ; Is it a NUL terminator?
    JNZ %%NEXTCHAR              ;     If not go back and get next character

%%ENDLOOP:
    STOSB                       ; Store NUL terminator at end of BARCODE

    RET

computeControlDigit ENDP
_TEXT ENDS
END

Конечно, вы выполняете любую обработку по вашему выбору.Я просто сделал прямую копию данных в качестве примера.

При использовании MASM вам, возможно, придется использовать немного другой синтаксис:

.MODEL LARGE, C

PUBLIC computeControlDigit

_DATA SEGMENT WORD PUBLIC 'DATA'
    BARCODE DB 13 DUP(?)
_DATA ENDS

_TEXT SEGMENT WORD PUBLIC 'TEXT'
ASSUME DS:_DATA, CS:_TEXT

computeControlDigit PROC FAR C USES DS SI DI barcodestr:DWORD    
; DS, SI, DI are saved as they are non-volatile registers
; barcodestr is a FAR pointer (DWORD)

    MOV AX, SEG BARCODE         ; Get segment and offset (FAR PTR) of BARCODE
    MOV ES, AX                  ; into ES:DI
    MOV DI, OFFSET BARCODE

    LDS SI, barcodestr          ; Load barcodestr FAR pointer into DS:SI
    JMP GETCHAR                 ; Get next character

NEXTCHAR:
    STOSB                       ; Store character to ES:DI (BARCODE), DI++
GETCHAR:
    LODSB                       ; Read character from DS:SI (barcodestr), SI++
    TEST AL, AL                 ; Is it a NUL terminator?
    JNZ NEXTCHAR                ;     If not go back and get next character

    STOSB                       ; Store NUL terminator at end of BARCODE

    RET

computeControlDigit ENDP
_TEXT ENDS
END

Необработанная версия без использования специальных директив ассемблера, которыеможет показаться более естественным для вас:

                PUBLIC  _computeControlDigit

_DATA           SEGMENT WORD PUBLIC USE16 'DATA'
BARCODE:
    DB  13 DUP(?)    
_DATA           ENDS

_TEXT           SEGMENT WORD PUBLIC USE16 'TEXT'
                ASSUME CS:_TEXT, DS:_DATA

_computeControlDigit:
        push            bp
        mov             bp,sp
        push            ds
        push            si
        push            di
        mov             ax,seg BARCODE
        mov             es,ax
        mov             di,offset BARCODE
        lds             si,dword ptr 6[bp]
        jmp             GETCHAR
NEXTCHAR:
        stosb
GETCHAR:
        lodsb
        test            al,al
        jne             NEXTCHAR
        stosb
        pop             di
        pop             si
        pop             ds
        pop             bp
        retf
_TEXT           ENDS
                END

Сноска

  • 1 LODSB и STOSB похожи к эквивалентному коду, показанному за исключением того, что LODSB и STOSB не изменяют флаги.
1 голос
/ 28 марта 2019

Вы можете использовать

        mov     al,es:[bx]

для чтения символа из строки, но так как это большая модель, вам нужно создать дальний указатель на BARCODE. Возможно, вы захотите использовать ds: si для ввода и es: di для вывода, поскольку это позволит коду lodsb и stosb.

...