如何将内存数据从指针复制到阵列ASSEMBLY 8086

问题描述 投票:1回答:2

我正在研究一个C程序,该程序调用将数组作为参数传递的汇编函数。在汇编代码中(用于8086),我能够在内存中获取数组的地址并将地址保存在ES:BX中,但是之后,我需要将值复制到数组BARCODE中,但是我可以找不到实现此目标的任何方法。

我的代码看起来像这样:

代码:

unsigned char computeControlDigit(char* barCodeASCII);

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

controlDigitCheck = computeControlDigit(barCodeStr);
}

Assemby代码:

_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

欢迎任何帮助。

c assembly masm x86-16 real-mode
2个回答
1
投票

在大内存模型中,所有数据和代码都是FAR,必须通过适当的段进行引用。在下面的代码中,我将指向源字符串barcodestr的指针加载到DS:SI中,将BARCODE的指针加载到ES:DI中。然后,我使用barcodestrLODSB数组中读取字符,然后使用BARCODE将其保存到STOSB。到达NUL终止符后,复制完成。

假设方向标记(DF)设置为0(向前移动):

  • STOSB1相似:

    STOSB
  • STOSB1相似:

    mov [ES:DI], al
    lea di, [DI + 1]              ; Increment DI by 1 without altering flags
    

我不知道您是使用MASM还是TASM作为汇编程序,因此我同时提供了两者的版本。仅复制NUL终止的字符串的示例TASM代码如下:

LODSB

当然,您可以进行任何选择的处理。我只是直接复制了数据作为示例。

如果使用MASM,则可能必须使用稍微不同的语法:

LODSB

没有使用特殊的汇编程序指令的原始版本,您可能会觉得更自然:

mov al, [DS:SI]
lea si, [SI + 1]              ; Increment SI by 1 without altering flags

脚注

  • 1 .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 .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 LODSB分别作为一条指令完整地执行。

1
投票

您可以使用

STOSB

要从字符串中读取字符,但是由于这是大型模型,因此您需要创建一个指向BARCODE的远端指针。您可能要考虑将ds:si用作输入,将es:di用作输出,因为这将使代码成为lodsb和stosb。

© www.soinside.com 2019 - 2024. All rights reserved.