• 締切済み

アセンブラーのプログラムに関して

アセンブラー/370の古いプログラムを明日までに解析しなければならなくなってしまいました。 プログラムは下記のようなものなのですが処理内容がわからず困っております。 つきましては… (1)もしお分かりになられる方がいらっしゃいましたら どのような処理を行っているか教えていただけないでしょうか? よろしくお願いします。   AH   2,=H'18'   STH  2,*+8   DC   X'F070'   DC   S(エリア名称)   DC   H'0'   BNH  RTN

みんなの回答

回答No.5

もうとっくにご本人には関係なくなっているでしょうが、ちょっと気になるコーディングですのでコメントしておきます。 (各インストラクションの解説は#4の回答を参照して下さい。) シフト対象のエリア長が8バイトになっているので、多分(エリア名称)で指定されている内容は15桁のパック10進数と考えられます。 そこで、レジスター2の内容がとても気になります。 仮にレジスター2の値が0だとすれば、左に18桁シフトすることになり、0以外の値であれば確実にオーバーフローしてしまいます。 最後のBNHではシフトの結果としてオーバフローしないで正の数字が残るケース以外はすべてRTNにブランチすることになっているので、ですからレジスター2が0だとすると、当該エリアの値が何であれエリアは結果的に0となりかつRTNにブランチします。 したがって、レジスター2にはなにか可変な値が入っていると見るのが妥当でしょうね。 この時注意しなければならないのは、STHで設定されるシフト桁数は6ビットの2の補数であることです。 すなわち32以上の数字が入っている場合はマイナスと見做し、右シフトになります。 しかし、実際のプログラムにこのようなコーディングがされることがあるのか、若干疑問に感じています。命令をDCで定義すること自体望ましくなく、その上命令の一部を実行時に書き換えているのも好ましくありません。レジスターの中身を判定して処理を分割すれば、多分意図する目的は確実に実現できるはずで、もっとシンプルなコーディングになるはずと考えられます。

  • backy0175
  • ベストアンサー率87% (102/116)
回答No.4

こんにちは。 もう返事は不要かもしれませんが、かつてSystem370でバリバリとアセンブラを書いていたので懐かしくてリプライします。   AH   2,=H'18' ← レジスタ2番にハーフワードの18を加える   STH  2,*+8 ← レジスタ2番をこの命令から数えて8バイト先に格納する(次の命令のパラメータ DC H'0' を変更している)   DC   X'F070' ← F0がSRP(Shift and Round Decimal)という命令 7が長さ-1なので、10進数で8、0は丸めの桁数   DC   S(エリア名称) ← パラメタ1のアドレス(ベースレジスタ+オフセット)   DC   H'0' ← パラメタ2(STHで設定される)   BNH  RTN ← パラメタ1がパラメタ2よりも大きく無い場合にRTNにブランチ 以上、古い記憶を遡って書きましたので、間違えている部分もあるかもしれませんが、よかったら参考になさってください。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

System/370のニーモニック表のようです http://www.simotime.com/asmins01.htm Branch命令 http://www.simotime.com/asmbch01.htm

参考URL:
http://www.simotime.com/indexasm.htm
soulbird12
質問者

お礼

ニーモニック表へのリンクありがとうございます。 私はニーモニックを理解するのにも四苦八苦するwレベルですが がんばって勉強していきたいと思います。 ありがとうございました。

  • mizmiz
  • ベストアンサー率45% (46/101)
回答No.2

これはIBMの汎用機のアセンブラでしょうか? 20年くらい前に汎用機のアセンブラの仕事をしたことがある程度でほとんど記憶にないのですが、当時すでにほとんど使われておらず特殊な用途で必要に迫られてやりました。 アセンブラ世代の人に教わりながらやったのですが、開発のベースとなったプログラムの解析で困ったのはプログラムでプログラム自身を書き換えることでステップ数を節約するといった手法が当たり前に使われていました。 提示のソースを見てもニーモニックを理解できるだけの記憶がないのでお役に立てそうにないのですが、上記のような手法を使っているのではないかと思います。 主にテーブルで複数分岐をする場合などですが、そういう可能性もあるという目で見れば理解の助けになるのではないでしょうか。 お役に立てないかもしれませんが参考までに。

soulbird12
質問者

お礼

そうですね。IBMの汎用機のアセンブラで370を使った プログラムになっていると思います。 お役に立てないなんてとんでもありません。 回答参考にさせていただきます。ありがとうございました。

回答No.1

これって連続した命令群ではなくて、分からない命令を部分的に抜き出したものですか? 処理内容というのは、それぞれの命令の意味を個々に知りたいということでしょうか?

参考URL:
http://homepage1.nifty.com/ttakao/370asm/index.html
soulbird12
質問者

補足

これって連続した命令群ではなくて、分からない命令を部分的に抜き出したものですか? →はい。一応連続した命令群となっています。 処理内容というのは、それぞれの命令の意味を個々に知りたいということでしょうか? →そうですね。今のままですと取っ掛かりもつかめない状態なので個々の意味だけでも分かると 大変ありがたいです。

関連するQ&A

  • 関数の積分を求めるプログラムで質問です。

    シンプソンの公式を用いて積分を求めるプログラムで、 「 y=1/(1+x*x) のように±∞で0に収束するような関数は以下のような無限積分を求めることができる。 ∫(-∞→∞){1/(1+x*x)}dx …(a) ただし、無限区間を分割することはできないので、コンピュータを用いた計算では ∫(-a→a){1/(1+x*x)}dx のaに大きな値を入れることで代用する。この積分を求めるプログラムをシンプソンの式を用いて作成し、以下の3ケースについて値を求めて真値と比較せよ。真値は式(a)を解析的に積分することで求めよ。 ・a=100、N=1000 ・a=100、N=500 ・a=200、N=1000 (Nは以下のプログラムと対応しているものです) 」 というもので参考としてS=∫(1→2){1/x}dxをシンプソンの公式を使い求めるものは以下のものなのですが #include <stdio.h> double f(double x) { return 1/x; } int main() { int i,N; double a,b,h,S; double x[1000],y[1000]; a=1.0; b=2.0; N=10; h=(b-a)/N; for(i=0;i<=N;i++) x[i]=a+i*h; y[0]=f(x[0]); y[N]=f(x[N]); S=h*(y[0]+y[N])/3.0; for(i=1;i<=N-1;i=i+2) { y[i]=f(x[i]); S=S+h*y[i]*4.0/3.0; } for(i=2;i<=N-2;i=i+2) { y[i]=f(x[i]); S=S+h*y[i]*2.0/3.0; } printf("N=%d,S=%15.10lf\n",N,S); } これを生かしてプリグラムをつくりたいのですが、分からなくて困っています。助けてください。

  • ヘロンの公式を作ったプルグラムなのですが、プログラムの間違いを教えてください。

    プログラムの間違いを教えてください ヘロンの公式を作ったプログラムなんですが・・・ #include <stdio.h> #include <math.h> void main(void) { float a,b,c,s,x; printf("三角形の三辺の長さを入れてください\n"); printf("a="); scanf("%f",&a); printf("b="); scanf("%f",&b); printf("c="); scanf("%f",&c); s=(a+b+c)/2; x= sqrt(s*(s-a)*(s-b)*(s-c)); printf("\n%f",x); }

  • fortranのプログラム

    fortranのプログラム 現在、fortranの勉強をしております。 そこで、質問があるのですが、 ある関数f(x,y,z)の座標(x,y,z)の値がデータとして与えられているとき、 S=10+f をfortranで計算したいと考えております。 ただ、関数fは複数(f1、f2、f3)あり、次々とfに代入してSを計算したいのですが、どのようにプログラムしたらいいか思いつきません。 どなたか、ヒントだけでもいいので、教えてください。 ちなみに、私が考えたプログラムは(下のプログラムはポイントだけ書いてあります。endやその他関係ないと思われるところは省いております。) do 100 k=1,3 S=S+fk(x,y,z) continue function f1 f1(s,t,u)=・・・ return end f2(s,t,u)=・・・ return end 使用しているバージョンは、fortran77(本当は90を使っているのですが、77だけで書いています)です。

  • H8 3052 のプログラムで、少数のべき乗計算

    H8 3052 のプログラムで、少数のべき乗計算がしたいです。 y=4610.6x^(-1.156) という計算を入れたいです。 H8 3052 ヘッダファイル 3052f.h stdio.h math.h メイン関数で 1 x2=ad1_val; 2 y2=4610.6*pow(x2,-1.156); 3 if(y2>20){s2_flag = CW;} 4 if(y2<20){s2_flag = CCW;} このプログラムだと動作しません。 1 x2=ad1_val; 2 y2=x2/2; 3 if(y2>150){s2_flag = CW;} 4 if(y2<150){s2_flag = CCW;} このプログラムだと動作しました。 2行目のpowの式のせいで動作エラーするみたいなんですけど、 pow関数はH8 3052 では使えないのですか? それとも他に書き足すことがあるのですか? pow関数が使えないのなら他に方法はないですか? コンパイラは CC38H.exe です。 お願いします。

  • 平均値の定理の問題の解き方

    以下の問題の解き方がわからず、困っています。 解くにはとけたのですが、あっているかどうかわかりません。 わかる方、ご指南よろしくお願いします。 【問題】 次の関数に対して、「平均値の定理(3)」において、a=0としたときのθを求めよ。即ち、定数またはhの関数として表せ。 但し、h≠0は、0に十分近い数とする。 ※「平均値の定理(3)」  f(a+h)=f(a)+hf'(a+θh), 0<θ<1 x^2 + 1 【解答】 まず、f(a+h)を求める。 f(x)=x^2+1なので、 f(a+h) = (a+h)^2+1 = a^2+2ah+1+1 = a^2+2ah+2...(1) 次に、f(x)=x^2+1なので、f(a)を求める。 f(a)=a^2+1...(2) 最後に、f'(a+θh)を求める。 hf'(x)=2xより、hf'(a+θh)=2h(a+θh)...(3) (1)(2)(3)を、f(a+h)=f(a)+hf'(a+θh)に代入して a^2+2ah+2=a^2+1+2h(a+θh) 両辺を整理して a^2-a^2+2-1=2h(a+θh)-2ah 1=2ah+h^2θ-2ah h^2θ=1 よって、h^2θ=1が答え。

  • FORTRANのプログラムについて

    program dat real x(100), y(100) s2=0 read(*,*) m,h open(7,file='test2.txt') do i=1,m read(7,*,end=200) x(i),y(i) s1=h/2*(y(1)+y(m)) s2=s2+h*(y(i)) s3=h*y(1) end do 200 close(7) sum=s1+s2-s3 write(*,*) 'sum=',sum end 台形公式を求めるプログラムを書いています。 テキスト形式でまずデータを取り込みます。 刻み幅はhです。ただしデータ数は未知数です。 上のようにプログラムを書いたのですが、うまく働きません。どうすればよろしいでしょうか? ご教授お願いします

  • C言語のプログラム

    C言語で2つの微分方程式をEuler法、Heun法、Runge-Kutta法により求めるプログラムを作りたい。ただし、初期条件はx=0,y=1とする。また、間隔Δxを変えたときの解の変化を調べたい。 Euler法のプログラムはどうにか分かったのですが、Heun法、Runge-Kutta法のプログラムがわかりません。 Euler法のプログラム #include_<stdio.h> #include_<math.h> int_main(){ __double__a=0; __double__b; __int_____m=10; __int_____n; __double__h; __double__x,y; __double__dydx; __int_____k; __double__e; __double__f; __printf("オイラー法計算例:y=e^x,_y=1/e^4x\n\n"); __//_y_=_e^x __b_=_1; __for(n=100;n<=10000;n*=100){ ____h_=_(b-a)/n; ____printf("y'_=_y:_h(=dx)_=_%.1e_(y=e^x)\n",h); ____x_=_a;_y_=_1; ____for(k=0;k<=n;k++)_{ ______x_=_k*h; ______if(k%(n/m)==0)_{ ________f_=_exp(x); ________e_=_fabs(y-f); ________printf("x=%.2f,_y=%f,_e^x=%f_er=%.0e\n", ________x,y,f,e); ______} ______dydx_=_y; ______y_=_y_+_dydx*h; ____} __} __printf("\n"); __//_y_=_1/e^4x __b_=_4; __for(n=100;n<=10000;n*=100){ ____h_=_(b-a)/n; ____printf("y'_=_-4y:_h(=dx)_=_%.1e_(y=1/e^4x)\n",h); ____x_=_a;_y_=_1; ____for(k=0;k<=n;k++)_{ ______x_=_k*h; ______if(k%(n/m)==0)_{ ________f_=_exp(-4*x); ________e_=_fabs(y-f); ________printf("x=%.2f,_y=%f,_1/e^4x=%f_er=%.0e\n", ________x,y,f,e); ______} ______dydx_=_-4*y; ______y_=_y_+_dydx*h; ____} __} __return_0; } 分かる方がいましたら、回答よろしくお願いします。

  • アセンブリプログラムの問題です。

    アセンブリプログラムの勉強をしているのですが、以下の問題がわかりません。 (1) 変数f, g, h, i, j はCのプログラム内で32ビットの整数として宣言されているものとする。 以下のCのステートメントをMIPSのアセンブリコードで表せ。 また、f, g, h, i, j の値がそれぞれ1, 2, 3, 4, 5 であるならば最終的なfの値はいくつか。 a. f = g + f + i ; b. f = g + (h + 2); (2) 変数f, g, h, i, jはそれぞれ$s0, $s1, $s2, $s3, $s4に割り当てるられているものとする。また、配列AとBのベースアドレスは、それぞれレジスタ$s6 と$s7 に割り当てられているものとする。 次のCのステートメントをMIPSのアセンブリコードで表せ。 a. f = g + h + B[4] ; b. f = g - A[ B[4] ] ; c. f = -g + h + B[1] ; d. f = A[ B[g] + 1 ] ; (3) (2)の設定において、次のMIPSのステートメントをCのステートメントで表せ。 また、可能ならばこのMIPSアセンブリコードを同じ機能を果たしながらMIPS命令の数が最小になるように書き直せ。 a. add $s0, $s0, $s1 add $s0, $s0, $s2 add $s0, $s0, $s3 add $s0, $s0, $s4 b. lw $s0, 4($s6) 以上です。わかるものだけでも良いので教えてもらえますでしょうか?

  • γ関数のプログラム(初心者です)

    以下のようにγ関数のプログラムを組みました。 とりあえず整数値を入力すれば、正しい値は返しているということがprintfの4で確認できました。 もとはfortranで組んだプログラムをCに置き換えました。 ですが、実際走らせてみると、4で値は確認できますがsegmentation faultが出てしまいます。 ですからサブルーチンファイル(ユーザー関数?)として利用できません。 何がいけないのでしょうか? 正しくyが帰ってくるようにどうなおしたらよいのか教えてください。 #include <stdio.h> #include <math.h> double gamma(double x) { double c[8],y,a,r,b,s; int i; a=1.; r=1.; c[1]=5.771916e-01; c[2]=9.882058e-01; c[3]=8.970569e-01; c[4]=9.182068e-01; c[5]=7.567040e-01; c[6]=4.821993e-01; c[7]=1.935278e-01; c[8]=3.586834e-02; printf("0 %f\n",x); while(1){ if(x>2.){ x=x-1.; a=a*x; printf("1 %f %f\n",x,a); } else if(x<1.){ a=a/x; x=x+1.; printf("2 %f %f\n",x,a); } else{ break; } } x=x-1.; for(i=1;i<8;i++){ b=(double)(i); s=(c[i]*((double)(pow(-1,b))) *((double)(pow(x,b)))); printf("3 %d %f\n",i,c[i]); r=r+s; } y=a*(r+(0.03586834*((double)(pow(-1,8)))*((double)(pow(x,8))))); printf("4 %f\n",y); return y; } main() { double x,y; printf("数字を入力してください。"); scanf("%lf",&x); printf("メインプログラム %lf\n",x); y=gamma(x); printf("%f\n",y); }

  • プログラムについてですが・・・

    今、画像処理の最小二乗法のプログラムを作成しているのですが、どうも上手く出力されません。以下のプログラムが、メインのプログラムでして、余分な #include は気にしないでください。画像の表示自体のプログラムは特に問題はありませんでしたので省きました。このプログラムにどんな問題があるか、わかりません。どなたか教えてください。 お願いします。 #include <math.h> #include <windows.h> #include <commdlg.h> #include <memory.h> #include <dos.h> #include <time.h> #include <wchar.h> #include <stdio.h> #include <iostream.h> #include "../DibFile.h" #include "ImageSDK.h" int n,n4,n5,n6,n7,n8,n9 ; double n10,n11 ; int n0[1000],n1[1000],n2[1000],n3[1000] ; n = 0 ; for(y = 0 ; y < h ; y++){   for(x = 0 ; x < w ; x++){ i = x+y*w ; if( *(buff1+i) == 0x00 ){                n0[n] = x ;                n1[n] = y ;                n2[n] = x*x ;                n3[n] = x*y ;                ++n ; } } } n5 = 0 ; n6 = 0 ; n7 = 0 ; n8 = 0 ; n9 = 0 ; for(n4 = 0 ; n4 < n ; n4++){ n5 += n2[n4] ; n6 += n0[n4] ; ++n7 ; n8 += n3[n4] ; n9 += n1[n4] ; } if((n6*n6-n7*n5) != 0){  n10 = ((n9*n6)-(n7*n8)) / ((n6*n6)-(n7*n5)) ;  n11 = (n8-(n5*n10)) / n6 ; for(x = 0 ; x < w ; x++){   y = (int) (n10*x+n11) ;    if(y < h && y > 0){  *(buff1+(x+y*w)) = 0x80 ;    } }

専門家に質問してみよう