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

时间:2019-03-27 21:19:47

标签: c assembly x86-16

我正在研究一个C程序,该程序调用将数组作为参数传递的汇编函数。 在汇编代码中(用于8086),无法获取内存中数组的地址,因此将地址保存在BARCODE中,但是之后我需要将值复制到tha数组unsigned char computeControlDigit(char* barCodeASCII); int main( void ){ char barCodeStr[14] unsigned char controlDigitCheck; controlDigitCheck = computeControlDigit(barCodeStr); } 中,但是我无法找到任何方法来实现这一目标。

我的代码如下:

Ccode:

_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

Assemby代码:

@Injectable()
export class AppGuard implements CanActivate {
  constructor(private store: Store<fromAppStore.AppState>) {}

  canActivate(): Observable<boolean> {
    return this.checkAppStore().pipe(
      switchMap(() => of(true)),
      catchError(() => of(false))
    );
  }
  checkAppStore(): Observable<boolean> {
    return this.store.pipe(select(fromAppStore.areAppsLoaded)).pipe(
      tap(loaded => {
        if (!loaded) {
          this.store.dispatch(new fromAppStore.LoadApps());
        }
      }),
      filter(loaded => loaded),
      take(1)
    );
  }
}

欢迎任何帮助。

2 个答案:

答案 0 :(得分:1)

您可以使用

        mov     al,es:[bx]

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

答案 1 :(得分:1)

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

STOSB 1 类似:

mov [ES:DI], al
inc di

LODSB 1 类似:

mov al, [DS:SI]
inc si

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

.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 LODSBSTOSB与所示的等效代码相似,除了LODSB和{{1} }请勿更改标志。