2011-10-14 15 views
2

私は、16ビット数に設定されたbutsの数をカウントし、その数(ビットセット)をAXのメインプロシージャに送り返すサブプロシージャを記述しようとしています。メインは、1の数を表示し、その数が偶数か奇数かを判断する必要があります。ビット数のカウント。 16ビットアセンブリパリティプログラム

私は左にシフトして桁上げで1を数えようとしています。問題は、私が「メイン」に戻ったときに、元の入力番号が「パリティ」に入れられた数ではなく、AXであるということです。私はなぜそれが変化しているのか分からない。

; (This does not work, see below) 

... 
    PUSH AX   ; input value 
    CALL PARITY  ; want this to change it in-place... 
    ... 
    POP  AX   ; ...so that this pops off the output value 
    CALL PUTDEC$ 

... 

PARITY PROC FAR PUBLIC USES CX DX DS 
    POP  AX   ; get argument from stack 
    ... 
    PUSH AX   ; put result back on stack 
    RET 

このウォン:私はこれの意図はPARITYがスタックに同じ場所でそれを残して、スタック上の引数を取り、その引数を修正することであることを前提としてい

;=================================================================== 
    ;     MAIN.ASM 
    ;=================================================================== 
     EXTERN GETDEC$:FAR 
     EXTERN NEWLINE:FAR 
     EXTERN PUTSTRNG:FAR 
     EXTERN PUTDEC$:FAR 
     EXTERN PUTBIN:FAR 
     EXTERN PARITY:FAR 
    ;=================================================================== 
     .MODEL LARGE 
     .STACK 512 
    ;=================================================================== 
    ; D A T A S E G M E N T D E F I N I T I O N 
     .DATA 
    NUMBER  DW ? 
    PROMPT  DB 'Enter a number: ' 
    BINDISPLAY  DB 'Number in binary: ' 
    ONESDISPLAY  DB 'Number of 1s: ' 
    ODDDISPLAY  DB 'The number of 1s is odd. ' 
    EVENDISPLAY DB 'The number of 1s is even. ' 
    ;=================================================================== 
    ; C O D E S E G M E N T D E F I N I T I O N 
     .CODE 
      ASSUME DS:DGROUP 
    ;=================================================================== 

    MAIN PROC 

     MOV  AX,DGROUP   ;SET DS-REGISTER TO POINT TO 
     MOV  DS,AX    ;DATA SEGMENT 
     MOV  ES,AX    ;AND ES ALSO 

     CALL NEWLINE 
     MOV  DI, OFFSET PROMPT 
     MOV  CX, SIZEOF PROMPT 
     CALL PUTSTRNG 
     CALL GETDEC$ 
     CALL NEWLINE 
     MOV  DI, OFFSET BINDISPLAY 
     MOV  CX, SIZEOF BINDISPLAY 
     CALL PUTSTRNG 
    CALL PUTBIN 
     PUSH AX 
     CALL PARITY 
    CALL NEWLINE 


     CALL NEWLINE 
     MOV  DI, OFFSET ONESDISPLAY 
     MOV  CX, SIZEOF ONESDISPLAY 
     CALL PUTSTRNG 
    POP AX 
     CALL PUTDEC$ 
     CALL NEWLINE 

    SUB DX, DX 
     MOV  BX, 2 
     DIV  BX 
     CMP  DX, 0 
     JNE  ODDS 

     MOV  DI, OFFSET EVENDISPLAY 
     MOV  CX, SIZEOF EVENDISPLAY 
     CALL NEWLINE 
     CALL PUTSTRNG 
     JMP  EXIT_PROGRAM 
ODDS:  
     MOV  DI, OFFSET ODDDISPLAY 
     MOV  CX, SIZEOF ODDDISPLAY 
     CALL NEWLINE 
     CALL PUTSTRNG  
EXIT_PROGRAM: 
    .EXIT 
     MOV  AX, 4C00H 
     INT  21H 
MAIN ENDP 
     END MAIN 

;;=================================================================== 
;    Veronica Kaufman 
;     CISP 310 
;    PARITY.ASM 
;=================================================================== 
     .MODEL LARGE  
;=================================================================== 
; D A T A S E G M E N T D E F I N I T I O N 
     .DATA 
ONES_COUNT  DW  0       
;=================================================================== 
; C O D E S E G M E N T D E F I N I T I O N 
     .CODE 
     ASSUME DS:DGROUP 
;=================================================================== 

PARITY PROC FAR PUBLIC USES CX DX DS 
    POP AX 
NUM_LOOP: 
    CMP AX, 0 
    JE END_PROGRAM 
    SHL AX, 1 
    JC INCREMENT 
    JMP NUM_LOOP 
INCREMENT: 
    INC ONES_COUNT 
    JMP NUM_LOOP 
END_PROGRAM: 
    MOV AX, ONES_COUNT 
    PUSH AX 
    RET 
PARITY ENDP 
     END PARITY 
+0

x86にはパリティフラグがありますか?結果の下位バイトだけで動作しますが、それでもかなり良いです。あなたが持っているコードでは、分岐を減らすために 'ADC'を使うことができます。 – harold

答えて

3

  1. CALLはスタックにリターンアドレスをプッシュします。
  2. PROC ... USESによって生成されたプロローグコードは、より多くのものをスタックにプッシュします。

あなたPARITY内部POP AX、あなたが実際に完全に異なる何かを飛び出し(その後、その場所に戻って何かを入れて)している - プロローグによって保存され、他のレジスタのおそらく1。右のそれを行うための

オプション:

  1. あなたが呼び出し規約は、ここで使用されていることを理解していれば、あなたがスタックにプッシュされたAXの場所を見つけることができる必要があり、最も可能性の高いいくつかの小さなでBPレジスタからオフセットされています(この場合、PROC生成されたプロローグコードが何を行うかを知るためにMASMを十分に理解していません)。

  2. またはPARITYの入力を受け取り、その出力をAXレジスタに直接戻します。この場合、あなたは(入力がAXにすでにある)CALL PARITYPUSH AXを削除し、代わりにCALL後に直接を、それを配置する必要があります(後にポップされます返された結果を、保存するために - 私はAXをすることを想定しています他の呼び出しによって破損する可能性があるため保存する必要があります)。 POP AXPUSH AXの両方をPARITYから削除します。

関連する問題