アセンブリ言語の配列のプログラムがわからない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ビルド

アセンブリ言語の配列のプログラムがわからない

#1

投稿記事 by ビルド » 3年前

前の質問は多くてややこしいので新しい質問にしました。
いつもすみませんが、今度は配列を用いてアセンブリコードで表示するのがわからなくて教えください。
(1) val, ass, assv命令を活用し,mem領域を配列のように使用して,キーボードから入力したデータを降順にソートして大きい順に表示する sml2のアセンブラプログラムを作成する。

3) 上記の課題(1),(2)とも実行時に与えるデータは,各自の学籍番号の10進表記7桁が abcdefg であるとき,abc,bcd,cde, def, efg, fga, gabの7つの10進表記を作り,それらを使用せよ.

コード:

C:\workC>sml2_trwin.exe test_valass.txt
   0:     nop      -1
   1:     ldi       0
   2:    read      -1
   3:     nop      -1
   4:     ass      11
   5:     ldi       0
   6:     val      11
   7:   print      -1
   8:     del      -1
   9:    halt      -1
Executing program...
+exec_inst: pc=0, stack_ptr=0, inst=nop, opr=-1
stack=<>
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-exec_inst: pc=1, stack_ptr=0, inst=nop, opr=-1
stack=<>
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=1, stack_ptr=0, inst=ldi, opr=0
stack=<>
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-exec_inst: pc=2, stack_ptr=1, inst=ldi, opr=0
stack=<0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=2, stack_ptr=1, inst=read, opr=-1
stack=<0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
? 1
-exec_inst: pc=3, stack_ptr=2, inst=read, opr=-1
stack=<1, 0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=3, stack_ptr=2, inst=nop, opr=-1
stack=<1, 0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-exec_inst: pc=4, stack_ptr=2, inst=nop, opr=-1
stack=<1, 0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=4, stack_ptr=2, inst=ass, opr=11
stack=<1, 0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
data = 1.
mem_addr = 11.
data 1 stored to mem[11].
-exec_inst: pc=5, stack_ptr=0, inst=ass, opr=11
stack=<>
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=5, stack_ptr=0, inst=ldi, opr=0
stack=<>
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-exec_inst: pc=6, stack_ptr=1, inst=ldi, opr=0
stack=<0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=6, stack_ptr=1, inst=val, opr=11
stack=<0, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mem_addr = 11.
mem[11] = 1 pushed.
-exec_inst: pc=7, stack_ptr=1, inst=val, opr=11
stack=<1, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=7, stack_ptr=1, inst=print, opr=-1
stack=<1, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1
-exec_inst: pc=8, stack_ptr=1, inst=print, opr=-1
stack=<1, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+exec_inst: pc=8, stack_ptr=1, inst=del, opr=-1
stack=<1, >
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-exec_inst: pc=9, stack_ptr=0, inst=del, opr=-1
stack=<>
mem[0..20]=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
(debug): stack_ptr = 0; If non 0, something is WRONG!
Execution terminated.
できるところまでやりました。
ちなみに
val 新規 配列の先頭となる mem[]の番地 operandの値(array_base)にstack topの値(disp)を加えた値(mem_addr=array_base+disp)で示されるmem[]の番地に格納されている値(mem[mem_adr])をstack topに移動し,pcを1増やす.(stack topの値は上書きされて, mem[mem_adr]に等しくなる)stack_ptrは変化しない.
ass 新規 配列の先頭となる mem[]の番地 operandの値(array_base)にstack topの1つ下の値(disp = stack[stack_ptr - 1])を加えた値(mem_addr = array_base + disp)で示されるmem[]の番地(mem[mem_adr])に,stack topの値(v)を格納し,stack_ptrを2減らす.pcを1増やす.
assv 新規 配列の先頭となる mem[]の番地 operandの値(array_base)にstack topの1つ下の値(disp = stack[stack_ptr - 1])を加えた値(mem_addr = array_base + disp)で示されるmem[]の番地(mem[mem_adr])に,stack topの値(v)を格納し,さらに値(v)をstack topの一つ下(stack[stack_ptr - 1])に格納する.stack_ptrは 1減らす.※注:pcの増加数の違いを除けば,assvは ass命令を実行後,元stack topに在った値 vを再度pushすることに相当する.ただし,ass命令実行後には vは mem上にあり stack上には無くなっているので,assv命令を使用しない場合には,v自体を知っている,もしくは memの何処に格納したかを知っていることが必要である.

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#2

投稿記事 by ビルド » 3年前

出来れば今日24:00までで、お願いします。

かずま

Re: アセンブリ言語の配列のプログラムがわからない

#3

投稿記事 by かずま » 3年前

ビルド さんが書きました: (1) val, ass, assv命令を活用し,mem領域を配列のように使用して,キーボードから入力したデータを降順にソートして大きい順に表示する sml2のアセンブラプログラムを作成する。
sml2 とは何ですか? ネットで検索しても出てきません。
ビルド さんが書きました: 3) 上記の課題(1),(2)とも実行時に与えるデータは,各自の学籍番号の10進表記7桁が abcdefg であるとき,abc,bcd,cde, def, efg, fga, gabの7つの10進表記を作り,それらを使用せよ.
(2) はどこにあるんですか?
ビルド さんが書きました:

コード:

C:\workC>sml2_trwin.exe test_valass.txt
   0:     nop      -1
   1:     ldi       0
   2:    read      -1
   3:     nop      -1
   4:     ass      11
   5:     ldi       0
   6:     val      11
   7:   print      -1
   8:     del      -1
   9:    halt      -1 
del命令の説明はどこにあるんですか?

かずま

Re: アセンブリ言語の配列のプログラムがわからない

#4

投稿記事 by かずま » 3年前

データの個数は 7 に固定で、挿入ソート。

コード:

    int n, i, x;               // mem[0], mem[1], mem[2]
    int a[7];                  // mem[3+0], mem[3+1], ..., mem[3+6]

    n = 0;                     // ldi 0; store 0
    do {
        x = read();            // read;  store 2
        i = n;                 // load 0; store 1
        while (i != 0) {       // load 1; cjump <end_while>
            if (a[i-1] < x)    // load 1; val 2; load 2; opr2 less; cjump <end_while>
                a[i] = a[i-1]; // load 1; load 1; val 2; ass 3
            else
                break;
            i--;               // load 1; ldi 1; opr2 sub; store 1
        }                      // jump <while>
// <end_while>:
        a[i] = x;              // load 1; load 2; ass 3
        n++;                   // load 0; ldi 1; opr2 add; store 0
    } while (n != 7);          // load 0; ldi 7; opr2 equ; cjump <do>
    i = 0;                     // ldi 0; store 1
    do {
        print(a[i]);           // load 1; val 3; print
        i++;                   // load 1; ldi 1; opr2 add; sotre 1
    } while (i != 7)           // load 1; ldi 7; opr2 equ; cjump <do>
    halt();                    // halt
アドレス 0 に nop を入れていません。

コード:

   0:   ldi     0
   1:   store   0
   2:   read    -1
   3:   store   2
   4:   load    0
   5:   store   1
   6:   load    1
   7:   cjump   22
   8:   load    1
   9:   val     2
  10:   load    2
  11:   opr2    less
  12:   cjump   22
  13:   load    1
  14:   load    1
  15:   val     2
  16:   ass     3
  17:   load    1
  18:   ldi 1
  19:   opr2    sub
  20:   store   1
  21:   jump    6
  22:   load    1
  23:   load    2
  24:   ass     3
  25:   load    0
  26:   ldi     1
  27:   opr2    add
  28:   store   0
  29:   load    0
  30:   ldi     7
  31:   opr2    equ
  32:   cjump   2
  33:   ldi     0
  34:   store   1
  35:   load    1
  36:   val     3
  37:   print   -1
  38:   load    1
  39:   ldi     1
  40:   opr2    add
  41:   store   1
  42:   load    1
  43:   ldi     7
  44:   opr2    equ
  45:   cjump   35
  46:   halt    -1
  
さて、どこが間違っているでしょうか?

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#5

投稿記事 by ビルド » 3年前

参考になりました。ありがとうございます。

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#6

投稿記事 by ビルド » 3年前

「どこがまちがっていますか?」
もしかして間違い探しですか?
だとすれば
19番目のところで
空白がすくない?

正解教えてください。

かずま

Re: アセンブリ言語の配列のプログラムがわからない

#7

投稿記事 by かずま » 3年前

「どこか間違っているでしょうか?」と聞いたつもりが、
「どこか」が「どこが」になっていました。

どんなデータを与えてどんな結果になったのかを
聞きたかったのです。
私は、sml2_trwin.exe なんて持っていませんから、
確かめようがありません。

sml0 か sml2 か知りませんが、
これは一般的ではない言語、あるいはプロセッサです。
それについての質問をするなら、
まずその説明をちゃんとしないと誰も答えられません。
命令セットの詳細を提示してから質問をするべきなんです。
別のトピックでまた質問をするなら、その命令セットの
説明のあるページへリンクを付けてほしいのです。

No.1 のプログラムの del命令ですが、これは何ですか?
私は、スタックトップの値を削除する、すなわち
pop を実行するものかな、と思ったんですが、
print のあとスタックは空になっているはずなので
それは実行できないのではないかと困惑しています。

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#8

投稿記事 by ビルド » 3年前

コード:

11	"del
"	新規	-1	operand無し(形式的に -1).stack topをpopし,その値をstoreせず単に捨てる.pcを1増やす.
12	prec	新規	関数の引数の個数(arity)	"関数の呼び出しの準備をするために用いる.この命令は call命令とペアとなり,call命令の直前に実行されなければならない.①prec命令実行前の b_regの値を fstackにpush. ②関数処理終了後(rtrn命令実行後)のprogram counter (pc)の値(戻り番地という)をfstackにpush.③operand(即値)が示す arity個の実引数を stack からpopして fstack にコピーする※.④pcを1増やす.
※③のコピーの順序は stackに先に積まれたものが fstackにも先に積まれるようにする.このため,少なくともpopあるいはpushの一方はsml0で用意したものとは別に(block_pop()やblock_push()など)用意する必要がある.または,このデータ移動のための専用の関数(block_mv())を用意する."
13	call	新規	insts内の関数の開始番地	関数呼び出しに用いる.この命令は prec命令とペアとなり,prec命令の直後に実行されなければならない.pcをoperand(即値)の値に変更する.つまり次に実行する命令番地は関数の開始番地となる.現状では jump命令と全く同じ.
14	dclv	新規	局所変数の個数	operandで指定された個数分の局所変数の領域を fstack に確保し,pcを1増やす.確保した領域は 0クリアする.
15	rtrn	新規	-1	operand無し.形式的に -1.関数の呼び出しから復帰する.base registerの値や pcの値を fstackから復元する.fstack_ptrは関数呼び出し前の関数frameの最後のデータの場所を指すようになる.具体的にはつぎの3処理を順に行う.①fstack_ptr = b_reg-1 とする.②pc = fstack[b_reg+1] とする.③b_reg = fstack[b_reg] とする.
16	stof	新規	fstack内局所変位	stackを popして,popされた値を fstack に格納し,pcを1増やす.値の操作は具体的にはつぎのようになる.dをoperandの即値とするとき, stackをpopし,popされた値を fstack[b_reg+2+d]に格納する.dのことを局所変位(local displacement)という.
17	lodf	新規	fstack内局所変位	operand(即値)が示す番地の fstack の値を stack にpushし,pcを1増やす.値の操作は具体的にはつぎのようになる.dをoperandの即値とするとき, fstack[b_reg+2+d]にある値を stackに積む.dのことを局所変位(local displacement)という.
18	putch	printc	ascii文字コード(即値)	operand(asciiコードで1文字分,即値)を表示し,pcを1増やす.stackは参照しないので,popはしない.
19	val	新規	配列の先頭となる mem[]の番地	operandの値(array_base)にstack topの値(disp)を加えた値(mem_addr=array_base+disp)で示されるmem[]の番地に格納されている値(mem[mem_adr])をstack topに移動し,pcを1増やす.(stack topの値は上書きされて, mem[mem_adr]に等しくなる)stack_ptrは変化しない.
20	ass	新規	配列の先頭となる mem[]の番地	operandの値(array_base)にstack topの1つ下の値(disp = stack[stack_ptr - 1])を加えた値(mem_addr = array_base + disp)で示されるmem[]の番地(mem[mem_adr])に,stack topの値(v)を格納し,stack_ptrを2減らす.pcを1増やす.
21	assv	新規	配列の先頭となる mem[]の番地	operandの値(array_base)にstack topの1つ下の値(disp = stack[stack_ptr - 1])を加えた値(mem_addr = array_base + disp)で示されるmem[]の番地(mem[mem_adr])に,stack topの値(v)を格納し,さらに値(v)をstack topの一つ下(stack[stack_ptr - 1])に格納する.stack_ptrは 1減らす.※注:pcの増加数の違いを除けば,assvは ass命令を実行後,元stack topに在った値 vを再度pushすることに相当する.ただし,ass命令実行後には vは mem上にあり stack上には無くなっているので,assv命令を使用しない場合には,v自体を知っている,もしくは memの何処に格納したかを知っていることが必要である.
これが命令表です。

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#9

投稿記事 by ビルド » 3年前

sml2のやつは学校で作成したオリジナルです。

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#10

投稿記事 by ビルド » 3年前

sml2のプログラムです。
sml2_conf.h

コード:

#ifndef _SML_CONF_H
#define _SML_CONF_H

/***
  size definition of data area 
 ***/
#define INSTS_SIZE 256
#define MEM_SIZE 256
#define STACK_SIZE 256
#define BUFFER_SIZE 256
#define FSTACK_SIZE 256

/***
  global data: types, tables and variables
 ***/
typedef enum _Mnemonic {/* sml0 operation codes */
  nop = 0, /* no operation; does nothing but increments pc          */
  ldi,/* load immediate; push the immediate operand on to the stack */
  opr1,/* opr1; execute an unary operation specified by its operand */
       /* opr1 is not yet implemented.                              */
  opr2,/* opr2; execute a binary operation specified by its operand */
  print,/* print; print the value of the stack top, and pop         */
  read,/* read; read an integer from keyboard and push it           */
  jump,/* jmp; jump to the code address specified by its operand    */
  cjump,/* cjump; pop and jump to the code address specified by the */
        /* operand if the popped value is 0 (false); proceed to the */
        /* next instruction, otherwise                              */
  store,/* store; pop and store the popped value to the memory      */
        /* address specified by the operand                         */
  load, /* load; push the memory value at the address specified by  */
        /* the operand                                              */
  halt,/* halt; stack machine halts                                 */
  del,
  prec,
  call,
  dclv,
  rtrn,
  stof,
  lodf,
  printc,
  val,
  ass,
  assv,
  readc
} Mnemonic;

typedef enum _Operator {/* unary and binary operators */
  /* binary arithmetic operators */
  add = 10,/* + */
  sub,     /* - */
  mul,     /* * */
  dvd,    /* / */
  mod,    /* % */
  /* binary comparison operators */
  less = 20,/* < */
  lseq,    /* <= */
  gteq,    /* >= */
  gtr,     /* > */
  equ,     /* == */
  nteq,    /* != */
  /* binary logical operators; not yet defined */
  and = 30,/* && */
  or,      /* || */
  xor,     /* ^  */
  /* unary arithmetic operators; not yet defined */
  plus = 40,   /* + */
  minus,       /* - */
  /* unary logical operator; not yet defined */
  not = 50     /* ! */
} Operator;

typedef struct code{
  Mnemonic ope;/* operation code; Mnemonic */
  int      opr;
  /* opr: an immediate value, an address, i.e., an index for mem[ ] */
  /* or insts[ ], displacement from b-reg, or an Operator;          */
  /* some operations neglect this field;                            */
} code_t;

typedef struct _MTable{
  char *codeName;
  Mnemonic code;
} MTable;

static const MTable mTable[] = {
  { "nop", nop },
  { "ldi", ldi },
  { "opr1", opr1 },
  { "opr2", opr2 },
  { "print", print },
  { "read", read },
  { "jump", jump },
  { "cjump", cjump },
  { "store", store },
  { "load", load },
  { "halt", halt },
  { "del", del}, 
  { "prec", prec}, 
  { "call", call}, 
  { "dclv", dclv}, 
  { "rtrn", rtrn}, 
  { "stof", stof}, 
  { "lodf", lodf}, 
  { "val", val },
  { "ass", ass },
  { "assv", assv },
  { "putch", printc },/* not yet implemented */
  { "readc", readc } /* not yet implemented */
};

typedef struct _OpeTable{
  char *codeName;
  Operator code;
} OpeTable;


static const OpeTable opeTable[] = {
  {"###", (Operator)0}, /* undefined operation */
  { "add", add },
  { "sub", sub },
  { "mul", mul },
  { "dvd", dvd },
  { "mod", mod },
  { "less", less },
  { "lseq", lseq },
  { "gteq", gteq },
  { "gtr", gtr },
  { "equ", equ },
  { "nteq", nteq },
  {"and", and},
  {"or", or},
  {"xor", xor},
  {"not", not}
};

#endif /* _SML_CONF_H */
sml2_ex4.c

コード:

#include <stdio.h>
#include "sml2_conf.h"
#include "sml2_lib.h"

/*
 global data
*/
extern code_t insts[INSTS_SIZE];
extern int pc;/* program counter; index for insts[ ] */

extern int mem[MEM_SIZE];

extern int stack[STACK_SIZE];/* stack[0] shall not be used */
extern int fstack[FSTACK_SIZE];
extern int stack_ptr;/* stack pointer; pointing to the last datum on the stack */
              /* if a halt instruction encountered, it is set to 1 */

extern int halt_flag;/* default is 0; set 1 to halt */

/***************************************************************/
/*** main function                                           ***/
/***************************************************************/
int main( int argc, char *argv[] ) {
  /* loading program */
  if ( argc == 2 ){
    fload_program(argv[1]);/*load a program file designated by argv[1]*/
  } else {
    load_program();/*use a hard-coded program in the load_program function*/
  }

  print_program();/*reverse assemble the virtual machine language in mem[ ]*/

  /* initialise */
  stack_ptr = 0;/*initialise stack pointer*/
  pc = 0;       /*initialise program counter*/
  halt_flag = 0;/* 1 is set when halt instruction is executed; 0 initially */

  /* execute *//* NO stack overflow check is done */
  printf("Executing program...\n");
  while (!halt_flag) {/*repeat until halt instruction will be encountered */
    exec_inst();/*execute current instruction insts[pc] */
  }
  printf("(debug): stack_ptr = %d; If non 0, something is WRONG!\n", stack_ptr);  printf("Execution terminated.\n");

  return 0;
}
sml2_exec_inst.c

コード:

#include <stdio.h>
#include "sml2_conf.h"
#include "sml2_lib.h"

#define SML0PROMPT
#define DEBUG

code_t insts[INSTS_SIZE];
int pc;/* program counter; index for insts[ ] */

int stack[STACK_SIZE];/* stack[0] shall not be used */
int stack_ptr;/* stack pointer; pointing to the last datum on the stack */

int mem[MEM_SIZE];

int fstack[FSTACK_SIZE];

int halt_flag;/* default is 0; set 1 to halt */

void exec_inst(void) {
  int num;
  switch (insts[pc].ope) {
    case nop: {
      pc++;
      break;
    }
    case ldi: {
      push(insts[pc].opr);
      pc++;
      break;
    }
    case opr2: {
      exec_opr2(insts[pc].opr);
      pc++;
      break;
    }
    case print: {
      printf("%d\n", pop());
      pc++;
      break;
    }
	  case del: {
      pop();
      pc++;
	  break;
    }
    case read: {
#ifdef SML0PROMPT
      printf("? ");/*prompting when reading*/
#endif
      scanf("%d", &num);
      push(num);
      pc++;
      break;
    }
    case jump: {
      pc = insts[pc].opr;
      break;
    }
    case cjump: {
      if (pop() == 0) {pc = insts[pc].opr;}
      else {pc++;}
      break;
    }
    case store: {
      mem[insts[pc].opr] = pop();
      pc++;
      break;
    }
    case load: {
      push(mem[insts[pc].opr]);
      pc++;
      break;
    }
    case halt: {
      halt_flag = 1;
      break;
    }
 
    case val: {
      mem[insts[pc].opr + stack[stack_ptr]] = stack[stack_ptr];
      pc++;
      break;
    }
	case ass: {
	  mem[insts[pc].opr + stack[stack_ptr - 1]] = stack[stack_ptr];
	  stack_ptr = stack_ptr - 2;
	  pc++;
      break;
    }
	case assv: {
	  int v;
	  v = stack[stack_ptr];
	  mem[insts[pc].opr + stack[stack_ptr - 1]] = v;
	  stack[stack_ptr - 1] = v;
	  stack_ptr = stack_ptr - 1;
	  pc++;
      break;
    }
    default: {/* any other instruction is neglected */
#ifdef DEBUG
      printf("Unknown instruction code <%d> at insts[%d].\n",  insts[pc].ope, pc);
#endif
      pc++; break;
    }
  }
}
sml2_exec_inst.c

コード:

#include <stdio.h>
#include "sml2_conf.h"
#include "sml2_lib.h"

extern int stack[STACK_SIZE];/* stack[0] shall not be used */
extern int stack_ptr;/* stack pointer; pointing to the last datum on the stack */

/*
  exec_opr2: execute binary operations
*/
void exec_opr2(int operator) {
  int opr1, opr2, result;
  switch (operator) {
    case add: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 + opr2); push(result);
      break;
    }
    case sub: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 - opr2); push(result);
      break;
    }
    case mul: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 * opr2); push(result);
      break;
    }
    case dvd: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 / opr2); push(result);
      break;
    }
    case mod: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 % opr2); push(result);
      break;
    }
    case less: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 < opr2); push(result);
      break;
    }
    case lseq: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 <= opr2); push(result);
      break;
    }
    case gteq: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 >= opr2); push(result);
      break;
    }
    case gtr: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 > opr2); push(result);
      break;
    }
    case  equ: {
      opr2 =  pop(); opr1 = pop();
      result = (opr1 == opr2); push(result);
      break;
    }
    case nteq: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 != opr2); push(result);
      break;
    }

    case and: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 && opr2); push(result);
      break;
    }
    case or: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 || opr2); push(result);
      break;
    }
     case xor: {
       opr2 = pop(); opr1 = pop();
       result = (opr1 ^ opr2); push(result);
       break;
   }
    case plus: {
      opr2 = pop(); opr1 = pop();
      result = (opr1 + opr2); push(result);
      break;  
   }
     case minus: {
     opr2 = pop(); opr1 = pop();
     result = (opr1 - opr2); push(result);
     break;
   }
     case not: {
     opr2 = pop(); opr1 = pop();
     result = (opr1 =! opr2); push(result);
     break;
   }
    default: {printf("Undefined operator(%d).\n", operator);}
  }
  return;
}
sml2_lib.h

コード:

#ifndef _SML_LIB_H
#define _SML_LIB_H
/* stack machine emulator with a simple loader */
/* No check for size violation is made. */

/************************************/
/*** main and major subfunctions  ***/
/************************************/
void exec_inst(void);/* analyse an instruction and exec */
void exec_opr2(int operator);/* analyse a binary operator and exec */

void load_program(void);/* load an sml0 program */
void set_code(int i, Mnemonic operation, int operand);
  /* stores a pair of operation and operand into insts[i]*/

/*********************
 *** functionalize ***
 *********************/

/* stack[]へ値をpushする
 *
 * 引数:int value スタックへ投入する値
 * 戻値:なし
 */
void push( int value );

/* stack[]から値をpopする
 *
 * 引数:なし
 * 戻値:スタックから取り出した値
 */
int pop( void );

/*******************************
 *** external file operation ***
 *******************************/

/* ファイルからプログラムを読み込む
 *
 * 引数:char* fname ファイル名
 * 戻値:0 … 成功
 *       1 … ファイルオープンエラー
 *       2 … その他のエラー
 */
int fload_program( char *fname );

/* プログラムを表示する
 *
 * 引数:なし
 * 戻値:なし
 */
void print_program();

/***************
 *** convert ***
 ***************/

/* 文字列をMnemonicへ変換
 *
 * 引数:char* str Mnemonic文字列
 * 戻値:操作命令(Mnemonic型)
 */
Mnemonic strtomne( char *str );

/* Mnemonicを文字列へ変換
 *
 * 引数:Mnemonic mne 操作命令(Mnemonic型)
 *       char* str Mnemonic文字列
 * 戻値:なし
 */
void mnetostr( Mnemonic mne, char *str );

/* 文字列を演算命令へ変換
 *
 * 引数:char* str 演算命令文字列
 * 戻値:演算命令
 */
Operator strtoope( char *str );

/* 演算命令を文字列へ変換
 *
 * 引数:Operator ope 演算命令
 *       char* str 演算命令文字列
 * 戻値:なし
 */
void opetostr( Operator ope, char *str );

#endif /* _SML_LIB_H */
sml2_loader.c

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sml2_conf.h"
#include "sml2_lib.h"

/*
  set_code: place a single sml0 assembler code at inst[i]
*/
extern code_t insts[INSTS_SIZE];

void set_code(int i, Mnemonic operation, int operand) {
  insts[i].ope = operation;
  insts[i].opr = operand;
  return;
}

/*
  load_program: a simple loader of sml0 machine code
*/
/* Gaussの公式による 1 から n(キー入力)までの和(繰返し計算なし) */
void load_program(void) {
  set_code( 0, read, -1);/* read an integer and stack it */
  set_code( 1, store, 0);/* var n (read)*/
  set_code( 2, load, 0);/* load n */
  set_code( 3, ldi, 1);/* constant 1*/
  set_code( 4, opr2, add);/* (n+1) */
  set_code( 5, load, 0);/* n */
  set_code( 6, opr2, mul);/* (n+1)*n */
  set_code( 7, ldi, 2);/* constant 2 */
  set_code( 8, opr2, dvd);/*  (n+1)*n/2 */
  set_code( 9, print, -1);/* print the datum at the stack top, and pop */
  set_code(10, halt, -1);/* halt the machine */
  return;
}

///* n(キー入力)から 1までの和(繰り返し計算) n+(n-1)+(n-2)+...+2+1 */
//void load_program(void) {
//  /* sample codes: calc.c */
//  set_code( 0, read, -1);/* read an integer and stack it */
//  set_code( 1, store, 0);/* var n (read); counted down until 0 */
//  set_code( 2, ldi, 0);
//  set_code( 3, store, 1);/* var sum = 0 */
//  set_code( 4, ldi, 1);
//  set_code( 5, store, 2);/* const one = 1 */
//  set_code( 6, ldi, 0);
//  set_code( 7, store, 3);/* const zero = 0; */
//  set_code( 8, load,  0);/* LOOP: */
//  set_code( 9, load,  3);
//  set_code(10, opr2, gtr);/* (n > 0)?*/
//  set_code(11, cjump, 21);/* if No then jump to FIN */
//  set_code(12, load, 1);
//  set_code(13, load, 0);
//  set_code(14, opr2, add);/* sum + n */
//  set_code(15, store, 1);/* sum = sum + n */
//  set_code(16, load, 0);/* n */
//  set_code(17, load, 2);/* 1 */
//  set_code(18, opr2, sub);/* n - 1 */
//  set_code(19, store, 0); /* n = n - 1 */
//  set_code(20, jump, 8); /* goto LOOP */
//  set_code(21, load, 1); /* set sum */
//  set_code(22, print, -1);/* print the datum at the stack top, and pop */
//  set_code(23, halt, -1);/* halt the machine */
//  return;
//}


/*******************************
 *** external file operation ***
 *******************************/

/* ファイルからプログラムを読み込む */
int fload_program( char *fname ){
  FILE *fp;
  char buf[BUFFER_SIZE];
  char *delimiter = " ,;\n\r";
  char *data;
  int index;
  Mnemonic operation;
  int operand;

  /* ファイルオープン */
  fp = fopen(fname, "r");
  if (fp==NULL){exit(1);}

  /* データ分析 */
  while (fgets(buf, BUFFER_SIZE-2, fp) != NULL) {
    data = strtok(buf, delimiter);/*address; decimal ascii*/
    index = atoi(data);/*index to insts[]*/
    data = strtok(NULL, delimiter);/*Mnemonic; name*/
    operation = strtomne(data);/*Mnemonic code*/
    data = strtok(NULL, delimiter);/*operand;*/
    if (operation == opr2) {/*opernad is binary operator*/
       operand = strtoope(data);/*binary ope code*/
    } else {/*operand is an integer*/
       operand = atoi(data);/*an integer*/
    }
    set_code(index, operation, operand);
  }

  /* ファイルクローズ */
  fclose(fp);

  return 0;
}


/* プログラムを出力する */
void print_program(void){
  Mnemonic inst;
  int operand;
  char str;

  int ip = 0;/*instruction pointer*/
  while(ip<INSTS_SIZE) {
    inst = insts[ip].ope;
    operand = insts[ip].opr;

    if (inst==opr2){/*binary operation instruction*/
	  opetostr(operand, &str);
      printf("%4d:%8s, %8s\n", ip, "opr2", &str);
    } else {
      printf("%4d:%8d, %8d\n", ip, inst, operand);
    }
    if (inst==halt) break;/*assuming halt is the last instruction in insts[]*/
    ip++;/*next instruction*/
  }

  return;
}

/***************
 *** convert ***
 ***************/

/* 文字列をMnemonicへ変換 */
Mnemonic strtomne( char *str ){
  int size = sizeof(mTable)/sizeof(mTable[0]);
  int i;/*index for mTable*/
  for (i=0; i<size; i++) {
    if (strcmp(str, mTable[i].codeName)==0) {
      return (mTable[i].code);
    }
  }
//  return (Mnemonic)nop;/*見つからなかった場合これが真意かどうか?*/
  return (Mnemonic)99;/*見つからなかった場合これが真意かどうか?*/
}



/* Mnemonicを文字列へ変換 */
void mnetostr( Mnemonic mne, char *str ){
  int size = sizeof(mTable)/sizeof(mTable[0]);
  int i;/*index for mTable*/
  for (i=0; i<size; i++) {
    if (mTable[i].code==mne) {
      strcpy(str, mTable[i].codeName);//codeNameは9文字以下と仮定
      break;
    }
  }
  if (i>=size) {/*Mnemonic codeが見つからなかった場合 */
    strcpy(str, "########");
  }
  return;
}


/* 文字列を演算命令へ変換 */
Operator strtoope( char *str ){
  int size = sizeof(opeTable)/sizeof(opeTable[0]);
  int i;/*index for opeTable*/
  for (i=0; i<size; i++) {
    if (strcmp(str, opeTable[i].codeName)==0) {
      return (opeTable[i].code);
    }
  }
  return 0;/*見つからなかった場合*/
}


/* 演算命令を文字列へ変換 */
void opetostr( Operator ope, char *str ){
  int size = sizeof(opeTable)/sizeof(opeTable[0]);
  int i;/*index for opeTable*/
  for (i=0; i<size; i++) {
    if (opeTable[i].code==ope) {
      strcpy(str, opeTable[i].codeName);//codeNameは9文字以下と仮定
      break;
    }
  }
  return;
}
sml2_stack.c

コード:

#include "sml2_conf.h"
#include "sml2_lib.h"

extern int stack[STACK_SIZE];/* stack[0] shall not be used */
extern int stack_ptr;/* stack pointer; pointing to the last datum on the stack */

/*********************
 *** functionalize ***
 *********************/

/* stack[]へ値をpushする */
void push( int value ){
  stack[++stack_ptr] = value;
  return;
}

/* stack[]から値をpopする */
int pop( void ){
  return (stack[stack_ptr--]);
}

よもやま
記事: 68
登録日時: 5年前
連絡を取る:

Re: アセンブリ言語の配列のプログラムがわからない

#11

投稿記事 by よもやま » 3年前

ビルド さんが書きました:sml2のやつは学校で作成したオリジナルです。
ビルドさん個人が作成されたものですかね。
学校から提供されているソースであるなら許可なくソースを掲示板などインターネット上に投稿(または公開)すると著作権法などに抵触しますよ。

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#12

投稿記事 by ビルド » 3年前

グループで作成したプログラムです。

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#13

投稿記事 by ビルド » 3年前

上記の文の間違いで、グループの自由課題です。だから、学校のオリジナルは間違いです。
そこで、ソートするプログラムができましたし、実行できました。

コード:

./sml2 ex.txt
   0:       0,       -1
   1:       5,       -1
   2:       8,        0
   3:       5,       -1
   4:       8,        1
   5:       5,       -1
   6:       8,        2
   7:       5,       -1
   8:       8,        3
   9:       5,       -1
  10:       8,        4
  11:       5,       -1
  12:       8,        5
  13:       5,       -1
  14:       8,        6
  15:       1,        7
  16:       8,       15
  17:       9,        6
  18:       9,        5
  19:    opr2,       23
  20:       7,       27
  21:       9,        6
  22:       8,       16
  23:       9,        5
  24:       8,        6
  25:       9,       16
  26:       8,        5
  27:       9,        5
  28:       9,        4
  29:    opr2,       23
  30:       7,       37
  31:       9,        5
  32:       8,       16
  33:       9,        4
  34:       8,        5
  35:       9,       16
  36:       8,        4
  37:       9,        4
  38:       9,        3
  39:    opr2,       23
  40:       7,       47
  41:       9,        4
  42:       8,       16
  43:       9,        3
  44:       8,        4
  45:       9,       16
  46:       8,        3
  47:       9,        3
  48:       9,        2
  49:    opr2,       23
  50:       0,        0
  51:       9,        3
  52:       8,       16
  53:       9,        2
  54:       8,        3
  55:       9,       16
  56:       8,        2
  57:       9,        2
  58:       9,        1
  59:    opr2,       23
  60:       7,       67
  61:       9,        2
  62:       8,       16
  63:       9,        1
  64:       8,        2
  65:       9,       16
  66:       8,        1
  67:       9,        1
  68:       9,        0
  69:    opr2,       23
  70:       7,       77
  71:       9,        1
  72:       8,       16
  73:       9,        0
  74:       8,        1
  75:       9,       16
  76:       8,        0
  77:       9,       15
  78:       1,        1
  79:    opr2,       11
  80:       8,       15
  81:       9,       15
  82:       1,        0
  83:    opr2,       23
  84:       7,       86
  85:       6,       17
  86:       9,        0
  87:       4,       -1
  88:       9,        1
  89:       4,       -1
  90:       9,        2
  91:       4,       -1
  92:       9,        3
  93:       4,       -1
  94:       9,        4
  95:       4,       -1
  96:       9,        5
  97:       4,       -1
  98:       9,        6
  99:       4,       -1
 100:      10,       -1
Executing program...
? 111
? 555
? 999
? 777
? 333
? 666
? 444
999
777
666
555
444
333
111
(debug): stack_ptr = 7; If non 0, something is WRONG!
Execution terminated.

ビルド

Re: アセンブリ言語の配列のプログラムがわからない

#14

投稿記事 by ビルド » 3年前

すみませんが、今度はperk, call, dclv, rtrn, stof, lodf を用いてキーボードから入力したデータを昇順にソートして小さい順に表示する プログラムでわかりません。
普通にソートするコードです。多分どこかの文に書き加えばできると思う。

コード:

0, nop, -1
1, read, -1
2, store, 0
3, read, -1
4, store, 1
5, read, -1
6, store, 2
7, read, -1
8, store, 3
9, read, -1
10, store, 4
11, read, -1
12, store, 5
13, read, -1
14, store, 6
15, ldi, 7
16, store, 15
17, load, 6
18, load, 5
19, opr2, gtr
20, cjump, 27
21, load, 6
22, store, 16
23, load, 5
24, store, 6
25, load, 16
26, store, 5
27, load, 5
28, load, 4
29, opr2, gtr
30, cjump, 37
31, load, 5
32, store, 16
33, load, 4
34, store, 5
35, load, 16
36, store, 4
37, load, 4
38, load, 3
39, opr2, gtr
40, cjump, 47
41, load, 4
42, store, 16
43, load, 3
44, store, 4
45, load, 16
46, store, 3
47, load, 3
48, load, 2
49, opr2, gtr
59, cjump, 57
51, load, 3
52, store, 16
53, load, 2
54, store, 3
55, load, 16
56, store, 2
57, load, 2
58, load, 1
59, opr2, gtr
60, cjump, 67
61, load, 2
62, store, 16
63, load, 1
64, store, 2
65, load, 16
66, store, 1
67, load, 1
68, load, 0
69, opr2, gtr
70, cjump, 77
71, load, 1
72, store, 16
73, load, 0
74, store, 1
75, load, 16
76, store, 0
77, load, 15
78, ldi, 1
79, opr2, sub
80, store, 15
81, load, 15
82, ldi, 0
83, opr2, gtr
84, cjump, 86
85, jump, 17
86, load, 0
87, print, -1
88, load, 1
89, print, -1
90, load, 2
91, print, -1
92, load, 3
93, print, -1
94, load, 4
95, print, -1
96, load, 5
97, print, -1
98, load, 6
99, print, -1
100, halt, -1
また、precなどの命令セットです。

コード:

prec	新規	関数の引数の個数(arity)	"関数の呼び出しの準備をするために用いる.この命令は call命令とペアとなり,call命令の直前に実行されなければならない.①prec命令実行前の b_regの値を fstackにpush. ②関数処理終了後(rtrn命令実行後)のprogram counter (pc)の値(戻り番地という)をfstackにpush.③operand(即値)が示す arity個の実引数を stack からpopして fstack にコピーする※.④pcを1増やす.
※③のコピーの順序は stackに先に積まれたものが fstackにも先に積まれるようにする.このため,少なくともpopあるいはpushの一方はsml0で用意したものとは別に(block_pop()やblock_push()など)用意する必要がある.または,このデータ移動のための専用の関数(block_mv())を用意する."
call	新規	insts内の関数の開始番地	関数呼び出しに用いる.この命令は prec命令とペアとなり,prec命令の直後に実行されなければならない.pcをoperand(即値)の値に変更する.つまり次に実行する命令番地は関数の開始番地となる.現状では jump命令と全く同じ.
dclv	新規	局所変数の個数	operandで指定された個数分の局所変数の領域を fstack に確保し,pcを1増やす.確保した領域は 0クリアする.
rtrn	新規	-1	operand無し.形式的に -1.関数の呼び出しから復帰する.base registerの値や pcの値を fstackから復元する.fstack_ptrは関数呼び出し前の関数frameの最後のデータの場所を指すようになる.具体的にはつぎの3処理を順に行う.①fstack_ptr = b_reg-1 とする.②pc = fstack[b_reg+1] とする.③b_reg = fstack[b_reg] とする.
stof	新規	fstack内局所変位	stackを popして,popされた値を fstack に格納し,pcを1増やす.値の操作は具体的にはつぎのようになる.dをoperandの即値とするとき, stackをpopし,popされた値を fstack[b_reg+2+d]に格納する.dのことを局所変位(local displacement)という.
lodf	新規	fstack内局所変位	operand(即値)が示す番地の fstack の値を stack にpushし,pcを1増やす.値の操作は具体的にはつぎのようになる.dをoperandの即値とするとき, fstack[b_reg+2+d]にある値を stackに積む.dのことを局所変位(local displacement)という.

返信

“C言語何でも質問掲示板” へ戻る