2016-09-14 4 views
0

私はアセンブリの初心者で、AT & T構文のLinux 64ビットでプログラミングしています。レジスタに数値1を格納すると、それをASCII文字 "A"にどのように変換できますか?たとえば:アセンブリー:数値をアスキーに変換して表示バッファーに書き込む方法

movl $1, %ebx 
addl $64, %ebx 

は、私が65(Aの小数点値)を作るために1に64を追加することができ、その後、何らかの形で「A」に変換し、writeシステムコールを使用してバッファにこれを送りますか?

EDIT 1:ここに自分のプログラムコードを掲載する。

.section .data 

message: 
     .long 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 

length: 
     .long 10 

.section .text 

.globl _start 

_start: 

xorq %rdi, %rdi 
xorq %rax, %rax 
xorq %rbx, %rbx 
xorq %rcx, %rcx     
xorq %rdx, %rdx 
movl length, %edx 

loop: 

     cmpl %ecx, %edx     
     je loop_end      
     movl message(,%rdi,4), %eax  
     addl $64, %eax     
     pushq %rax      
     incq %rdi      
     incq %rcx      
     jmp loop       



loop_end: 

     cmpq $0, %rcx     
     je exit       
     popq %rbx      
     pushq %rcx 
     movq $1, %rax 
     movq $1, %rdi 
     movq %rbx, %rsi     
     movl length, %edx 
     syscall       
     popq %rcx 
     decq %rcx 
     jmp loop_end 

exit: 

     movq $60, %rax 
     movq $0, %rdi 
     syscall 
+0

はい、あなたもあなたのコードはより人間に読みやすくするために、$「A」を追加 '%のebx'を使用して、定数の目的を文書化することができます。文字は*整数なので、メモリにそのバイトを格納し、そのメモリへのポインタをwrite(0、buf、1)に渡します。 –

+0

しかし、定数を使用したくない場合は、 %ebxの$ 65を 'A'に変換しますか? asciiに変換されるそれらの操作はありますか? – Mic

+0

一時バッファを作成します。それに文字を入れます(65は既に文字を表す値です)。 'sys_write'システムコールにバッファのアドレスを渡します。 –

答えて

0

私は& T構文ATと完全に慣れていないんだけど、あなたが慣れているものでNASMの分解が十分でなければなりません。

ハードコーディング定数と呼ばれるものを避けるようにしてください。プログラムのメンテナンスが難しくなります。特に、何千もの長さではありません。したがって、

  section .data  
Values:  db  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 26, 18, 12, 20, 19, 11 
V_Size  equ  $ - Values 

あなたが何をしたか、この

message: 
    .long 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 

length: 
    .long 10 

に望ましい間違っていないですが、この方法は、アセンブラでは、あなたのカウントに応じていない前提としています。すでに指摘されているように、ジョブを実行するために必要な最小データサイズを使用します。この場合、チャーはNASM

 section .text 
    global _start 

_start: xor  ecx, ecx 
     push rcx     ; Applications default return value 
     mov  cl, V_Size 
     push rcx 
     mov  ebx, Values 
     push rbx 

    Next: 
     or  byte [ebx], 64 
     inc  ebx 
     loop Next 

     pop  rsi 
     pop  rdx 
     pop  rax 
     inc  al 
     mov  edi, eax 
     syscall 

     mov  edi, eax 
     dec  edi 
     mov  eax, edi 
     mov  al, 60 
     syscall 

     section .data  
Values:  db  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 26, 18, 12, 20, 19, 11 
V_Size  equ  $ - Values 

このコード長い

よりも良好である "K" の後すぐにコマンドプロンプトで

ABCDEFGHIJZRLTSK

をもたらします。

  section .data: 
6000d8 01020304 05060708 090a1a12 0c14130b 

     section .text: 

<_start>: These two instructions are idiosyncratic to my style of programming and not 
      essential to functionality of program. 

    4000b0: 31 c9     xor %ecx,%ecx 
    4000b2: 51      push %rcx 

      Setup RCX & RBX for LOOP instruction 

    4000b3: b1 10     mov $0x10,%cl 
    4000b5: 51      push %rcx     ARG2 to syscall 
    4000b6: bb d8 00 60 00   mov $0x6000d8,%ebx 
    4000bb: 53      push %rbx     ARG1 to syscall 

<Next>:  This conforms to the scope of your objective. 

    4000bc: 67 80 0b 40    orb $0x40,(%ebx)   [ebx] += 'A' 
    4000c0: ff c3     inc %ebx 
    4000c2: e2 f8     loop 4000bc <Next> 

      ssize_t write (int fd, const void *buf, size_t count); 

    4000c4: 5e      pop %rsi     ARG1 = ASCII Pntr 
    4000c5: 5a      pop %rdx     ARG2 = # of chars 
    4000c6: 58      pop %rax 
    4000c7: fe c0     inc %al     SYS_WRITE 
    4000c9: 89 c7     mov %eax,%edi   ARG0 = STD_OUT 
    4000cb: 0f 05     syscall 

      Epilogue: Again, just a method I use. 

    4000cd: 89 c7     mov %eax,%edi 
    4000cf: ff cf     dec %edi 
    4000d1: 89 f8     mov %edi,%eax 
    4000d3: b0 3c     mov $0x3c,%al 
    4000d5: 0f 05     syscall 
+0

なぜシステムコール用のレジスタを設定するために、このような奇妙な非コメントNASMコードを使用していますか?あなたのSYS_exit(eax = 60)は正の値(エラーコードではありません)を返す書き込みに依存しているようです。だから './a.out>/dev/full'、' ./a.out>& - '(close stdout)や他の方法でプログラムを' eax = 0xFFFFFF3c'で 'syscall'を実行させることができますsys_writeを失敗させる。カーネルは、システムコール番号(x86-64システムコール番号は現在のところ '__NR_execveat 322 'に上る)については、ALだけでなくEAX全体を調べます。ああ、あなたはAT&Tの災害のアウトプットにコメントしているのですが、何も説明していません。 –

+0

終了ステータスをwrite()に依存させたいとしても、同じコードを書ける普通の方法は命令の半分です:lea edi、[rax-1]/'mov eax、SYS_write'です。あなたの混乱するmov/dec/mov/mov immにはゼロの利点があります。 –

+0

同様に、あなたの狂ったPUSH/POPコードよりも前に、ゼロの利点と多くの混乱があります。 'xor ecx、ecx' /' mov cl、V_Size'はMOV r32、imm32に対して1バイトを保存し、V_Sizeが8ビットに収まる場合にのみ動作します。 (あなたが言ったように、あなたのプログラムにハードコーディングの仮定を避けてください!)また、命令を浪費します。これは、AMD64をサポートしているCPU上の複数のコードバイトに関係します。 [LOOPはあなたが使うべきではない非常に遅い命令です。](http://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it効率的) –

関連する問題