2016-12-15 24 views
0

アセンブリ言語を使用して単純なコサイン(x)波をプロットする必要があります。私は教授の指示に従ってプロジェクトのすべてのステップを完了しましたが、プログラムを正しく印刷することができません。これは、ここでNASM x86アセンブリを使用して余弦波をプロットする

    *****     
       *  *     
       *  *     
       *   *    
       *   *    
      *    *    

      *    *    
      *     *   

      *     *   

     *      *   
     *      *   

     *       *  
     *       *  
    *        *  
    *        *  
    **         ** 
**          ** 

が私のコードです...、私が得る出力され

linux2[14]% cat plot4.out 
***************************************** 

しかし、それはする必要があります。いかなる援助も感謝します。

 SECTION .data   ; Data section, initialized variables 
nrow:   dq 21  ; 21 rows 
ncol:   dq 41  ; 41 columns 
fmtc:   db "%c", 0 ; print one character at a time 
fmtend:   db 10, 0 ; end a line 
star:   db '*'  ; one character '*' 
fmtendLen: equ $-fmtend 
pStar:  db "*" 
starLen: equ $-pStar 
pSpace:  db " " 
spaceLen: equ $-pSpace 
len:   equ $-star 
spc:   db ' ' 
af:   dq 1.0, 0.0, -0.5 ; coefficients of polynomial, a_0 first 
      dq 0.0, 0.041667, 0.0, -0.001389, 0.0, 0.000025 
XF:   dq 0.0  ; computed 
Y:   dq 0.0  ; computed 
N:   dq 8  ; power of polynomial 
X0:   dq -3.14159  ; start XF 
DX0:   dq 0.15708  ; increment for XF ncol-1 times 
one:   dq 1.0 
ten:   dq 10.0 
none:   dq -1.0 
nten:   dq -10.0 
twenty:   dq 20.0 
zero:   dq 0.0 
newline: db 10 

    section .bss 

a2: resb 21*41  ; two dimensional array of bytes 
i: resq 1  ; row subscript 
j: resq 1  ; col subscript 
k: resq 1 

    SECTION .text ; Code section. 

    global _start ; the standard gcc entry point 
_start:      ; the program label for the entry point 


;;; clear a2 to space 
    mov  rax,0   ; i=0 
    mov  [i],rax 

loopi: 
    mov  rax,[i] 
    mov  rbx,0  ; j=0 
    mov  [j],rbx 
loopj: 
    mov  rax,[i] 
    mov  rbx,[j] 
    imul rax,[ncol] ; i*ncol 
    add  rax, rbx ; i*ncol + j 
    mov  dl, [spc] ; need just character, byte 
    mov  [a2+rax],dl ; store space 

    mov  rbx,[j] 
    inc  rbx   ; j++ 
    mov  [j],rbx 
    cmp  rbx,[ncol] ; j<ncol 
    jne  loopj 

    mov  rax,[i] 
    inc  rax   ; i++ 
    mov  [i],rax 
    cmp  rax,[nrow]  ; i<ncol 
    jne  loopi 

;;; end clear a2 to space 

    mov  rax, 0   ;i = 0 
    mov  [i], rax 
    mov  rbx, 0   ;j = 0 
    mov  [j], rbx 

cos: 
    mov  rcx,[N]   ; loop iteration count initialization, n 
    fld  qword [af+8*rcx] ; accumulate value here, get coefficient a_ 
h5loop: 
    fmul qword [XF] ; * XF 
    fadd qword [af+8*rcx-8] ; + aa_n-i 
    loop h5loop   ; decrement rcx, jump on non zero 
    fstp qword [Y]   ; store Y 


;;; ; ; compute k 
    fld qword [Y] 
    fadd qword [one] 
    fmul qword [ten] 
    fmul qword [none] 
    fadd qword [twenty] 
    fistp qword [k] 

;;; ; ; ; ; rax gets k * ncol + j 
    mov  rax, [k] 
    mov  rbx, [j] 
    imul rax, [ncol] 
    add  rax, rbx 

;;; ; ; put "*" in dl, then dl into [a2+rax] 
    mov  dl, [star] 
    mov  [a2+rax], dl 

;;; ; ; XF = XF + DX0 
    fld  qword [XF] 
    fadd qword [DX0] 
    fistp qword [XF] 


    mov  rbx, [j] 
    inc  rbx   ; j++ 

    mov  [j], rbx 
    cmp  rbx,[ncol] ; j<ncol 
    jne  cos 

;;; print 
    mov  rax,0  ; i=0 
    mov  [i],rax 

ploopi: 
    mov  rax,[i] 
    mov  rbx,0  ; j=0 
    mov  [j],rbx 

ploopj: 

    mov rax,[i] 
    mov rbx,[j] 
    mov dl, [spc] 

    imul rax,[ncol] 
    add  rax, rbx 


    mov  rax, [i]  ; a2+i*ncol+j is byte 
    imul rax, [ncol] 
    add  rax, [j] 
    add  rax, a2 
    mov  rsi, rax ; address of character to print 
    mov  rax, 1  ; system call 1 is write 
    mov  rdi, 1  ; file handle 1 is stdout 
    mov rdx, 1  ; number of bytes 
    syscall   ; invoke operating system to do the write 

;;; print here 

    mov  rbx,[j] 
    inc  rbx   ; j++ 
    mov  [j],rbx 
    cmp  rbx,[ncol] ; j<ncol 
    jne  ploopj 

    mov  rdi, fmtend 
    mov  rax, 1 
    mov  rdi, 1 ; file handle 1 is stdout 
    mov  rsi, newline ; address of string to output 
    mov  rdx, 1  ; number of bytes 
    syscall 

;;; print here 

    mov  rax,[i] 
    inc  rax   ; i++ 
    mov  [i],rax 
    cmp  rax,[nrow]  ; i<ncol 
    jne  ploopi 

;;; print a2 

    mov  eax, 60 ; system call 60 is exit 
    xor  rdi, rdi ; exit code 0 
    syscall    ; invoke operating system to exit 
+0

単一のステップにあなたのプログラムをデバッガを使用して、それがうまくいかない場所を確認。 – Jester

+0

これは本当に愚かなことかもしれません...しかし、あなたはそれを行う方法を教えてください。 – marz123

+2

を使用すると、デバッガに精通していない場合、それは'ddd'のようなGUIを使って何かをつかむのが最も簡単かもしれません。トン。私はあなた自身がそれを見つけることができると信じています、ここでのコメントでデバッガを使う方法を教えてはいけません。 – Jester

答えて

3

[XF]更新が間違っているため、コードが期待どおりに動作しません:あなたはXFを修正します後

fistp qword [XF] ; will store integer. 

、それがクラッシュします計算のyの値は外なるので、[0,0] - > [41,21]座標。

星を描画する前に最小/最大座標クランプを追加することでコードをより堅牢にすることができます。計算結果が間違っている場合(x、y)、いくつかのメモリに星印は書き込まれませんy = 0に'#'があると、グラフがどこに間違っているかが分かります)。

その後、グラフを修正したいと思うかもしれません。それはあなた次第です。

とにかく、私はあなたのアセンブリテクニックについてコメントしています(または、コメントから指摘したように、インストラクターのテクニック)。私はそれを学生の仕事として容認することができますが、それだけです。

コンピュータプログラマになるには、文字通りすべての愚かさをコンピュータコマンドに変換するだけではありません。人々がそのようにプログラムするならば、並べ替えはすべての場合にまだ完全なO(n^2)になり、誰も圧縮アルゴリズムを作成することはありません。可能であれば、どのような計算方法を基本的に理解し、単純化するかを検討する必要があります。

コードから例を挙げておきます。最初の部分はa2配列のすべての位置にスペース文字を入れています。だから本質的にそれをやっている:

for (i = 0; i < 21; ++i) 
    for (j = 0; j < 41; ++j) 
    a2[i * ncol + j] = ' '; 

私はそれを持っている小さな問題があります..それは文字通り行われます。すべての式のすべてのf * ckingサインと同様に、すべてがCPUに存在するレジスタのように前後にメモリにロード/ストアされます。

しかし、さらに悪いことに、私もそれに大きな問題があります。プログラマの帽子を置いて、その部分でどのような計算が行われているのか考えてみると、計算の最終状態はa2に割り当てられたメモリ全体が値32' ')で満たされていることがわかります。そして、a2は連続して21 * 41バイトのメモリを占有します。これは、スペースで全体a2を記入します

lea rdi,[a2] ; address of first byte of a2 
lea ecx,[i-a2] ; rcx = size of a2 array in bytes 
; (using label "i" after it) And only ecx as 21*41 < 2^32 
mov al,' '  ; space value directly (why [spc]?) 
rep stosb  ; fill rcx bytes at rdi with al 

:だから、あなたは、このコードを書くことと同じことを行うために

。これらのループが列で行われる場合、このコードは行ごとに異なる方法で入力されます。しかし、計算の結果(配列全体が' 'に設定されている)にのみ関心がある場合は、行、列または円で行われたかどうかは気にしません。

など、...そのコードには奇妙なものがいくつかありますが、私はそれを私の好みに合わせて書き直すつもりはありません。これが私の考えを説明するのに十分だと思います。


ところで、私もrep stosbバリアント(およびそれにすぐに終了する学生は、さらに16または32乗の大きさであることがa2をパディングすることで、パフォーマンスのために最適化され、いくつかのSSEとそれを埋めることができます期待していません指示または少なくともstosd)。

しかし、少なくともあなたが行うことながら、内側のループは...すべての反復でi * ncol + jをやっている認識:

for (i = 0; i < 21; ++i) { 
    rowindex = i*ncol + 0; 
    for (j = 0; j < 41; ++j) { 
    a2[rowindex] = ' '; 
    ++rowindex; 
    } 
} 

...それは最低限のようなものです。そして、あなたはあなたが唯一のrowindex = 0;先の両方forループの実行する必要があるのでrowindex = i*ncol + 0;は、前の行の末尾から、既に設定された値に等しいことに気づくだろう、ということをデバッグするかどう:

charindex = 0; 
for (i = 0; i < 21; ++i) 
    for (j = 0; j < 41; ++j) 
    a2[charindex++] = ' '; 

そして今、あなたが既に表示されるはずです2つのforループは1つのfor (count = 0; count < 21*41; ++count)で置き換えることができますが、1秒待つと、それはcharindexと等しくないのですか?ああ、そうです。

for (i = 0; i < 21*41; ++i) a2[i] = ' '; 

そして、それは私のrep stosbのと同等だが、(あなたがrep stosbを知らないので)あなたがループのような単純なmov/inc/dec/jnz命令でこれを書くならば、私は(それがで実行されるだろう、それと完全に罰金だろうほぼ同じ時間)。

しかし、21 * 41 imul命令を実行することは...冒涜のようなものです。時間がありました.32ビットの数値を800回乗算すると約3〜5秒かかります。今や、そのコンピューティングパワーを使用して、バイトの連続した配列をクリアしています。痛み...


ところで、これはあなたの元のコードの出力である([XF]更新を固定し、その値をクランプ...と私はドットでスペースを置き換え、及びYの値が#*をオンにクランプされた後。

.......................*################# 
......................................... 
......................................... 
......................................... 
......................................... 
*.....................*.................. 
.*....................................... 
..*...................................... 
......................................... 
...*.................*................... 
......................................... 
....*.................................... 
.....*..............*.................... 
......................................... 
......*............*..................... 
.......*................................. 
........*.........*...................... 
.........*.......*....................... 
..........*.............................. 
...........*...**........................ 
............***.......................... 
+0

これをすべて説明する時間をとって本当にありがたいですが、この時点で私は失われています。何が起こっているのかわからない – marz123

+1

@MohammadMarzooghianこれは組立学校のコースであれば、もっと簡単なものから始めると思います。すぐにこれを開始した場合は、自分でチュートリアルを見つけるか、先生に紹介してもらうようにしてください。より簡単なチュートリアルを進めながら、歌の歌詞のような特定のパターンを覚えて指示を覚えてはいけません。それはあなたをどこにも連れてこないでしょう。あなたはCPU +メモリの数学、各命令でビット値がどのように変化しているかを理解する必要があります。どのように元のアルゴリズムにマップし、プログラムの出力を構築します。 – Ped7g

+0

fld qword [X0] fstp qword [XF]; cosの前にXFを初期化する必要があります。 fistp qword [k]; fstpでない fstp qword [XF];フィストなし – marz123

関連する問題