2つの正数の中で大きい方の数を出力するプログラムなんですが、演算命令(ADD、SUB)、飛び越し命令(JMP、JMZ)、転送命令(LDM、LDC、STR)を用いて、作成できるのでしょうか。かなり考えたのですが、よくわかりません。どんな回答でも結構ですので、宜しくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

どういうアーキテクチャをもつCPUを想定しているのでしょう?


ニーモニックで想像できるものもありますが、各転送命令の機能が
正確にわかりません。

JMZが0のときのジャンプを表していて、それ以外に条件ジャンプが
ないとすると、引き算の結果の正負の判断が直接にはできなさそう
です。AND演算くらいあればなんとかなりますが、それもないとい
うわけですね?

エレガントさを求めないなら、1ずつ引いていって、先に0になった
方が小さいというのでどうですか?私もあえて解は割愛しときます。
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/01/17 08:27

言語はCASLでしょうか?



基本的に二つの正数(仮にAとB)とします。
A-BでマイナスだったらBを出力する用にジャンプし、逆だったらAへという具合にプログラムを組みましょう。

あえて考え方だけ明記しておきます。ロジックは各演算命令と飛び越し命令の意味を確認すれば、コーディング出来ると思います。
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/01/17 08:27

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QCASL アセンブラ命令 アプリ機能

例えば、CASLのアセンブラ命令にDCがある。
LABER DC 100 とすると。
これは、メモリに領域を確保し100をいれる命令だが、プログラムが変更されれば、メモリアドレスは変更される。

CASLには機械語命令・マクロ命令・アセンブラ命令がある。

機械語命令は人に分かりやすいようにニーモニックが付けられているだけだが、
アセンブラ命令はプログラムが変更されればそのアドレスは移動するという、ハンドアセンブリでは、できない機能が含まれている。

アセンブリ言語は色々ありますが、アセンブラ言語は人に見やすいようにニーモニックが付けられているだけでなく、CASLのDC命令のように、ハンドアセンブリではできないアドレスの自動変更のようなアプリケーションとしての機能(OS的機能)も一般にふくまれているとかんがえてよいのでしょうか?

よろしく願います。

Aベストアンサー

No1です。

>プログラムの変更==>DCでアドレスの自動変更

DC命令に限らず、命令につけられたアドレスが何番地であるかを計算(カウントアップ)するのは、アセンブラの基本機能です。これがないと、生成した機械語命令を何番地に格納したらいいのかわからない。

>という、アセンブラ言語が単にニーモニックの記述だけでない、アプリとしての機能(OS的機能)が含まれているかという質問です。

アセンブラはアプリなので、ニーモニックを解釈したり、上記のアドレスの計算をしたりするのは、アセンブラというアプリの機能です。OSは関係ありません。OSの上でアセンブラというアプリが動いているだけ。

>LABER DC 100 とすると。
>これは、メモリに領域を確保し100をいれる命令だが、プログラムが変更されれば、メモリアドレスは変更される。

もしかして勘違いがあるかもしれませんが、
LABER DC 100
というのは、
「LABERという名前のラベルを現在の命令格納アドレスポインタの値で定義して、そのアドレスの1ワードに100を入れて、命令格納アドレスポインタを+1する」
で、
LABEL NOP
という機械語命令は、
「LABELという名前のラベルを現在の命令格納アドレスポインタの値で定義して、そのアドレスの2ワードにNOPの命令コードを入れて、命令格納アドレスポインタを+2する」

と、いうことで、DC命令と機械語命令はアセンブラの動作(ソースファイルをアセンブルして命令コードファイルを作る際の動作)としては格納するデータがちょっと違うだけです。DS命令も、データの長さが1とか2でなく可変であることと、データに何が入るか分からないというくらいの違いだけです。

No1です。

>プログラムの変更==>DCでアドレスの自動変更

DC命令に限らず、命令につけられたアドレスが何番地であるかを計算(カウントアップ)するのは、アセンブラの基本機能です。これがないと、生成した機械語命令を何番地に格納したらいいのかわからない。

>という、アセンブラ言語が単にニーモニックの記述だけでない、アプリとしての機能(OS的機能)が含まれているかという質問です。

アセンブラはアプリなので、ニーモニックを解釈したり、上記のアドレスの計算をしたりするのは、アセンブラとい...続きを読む

Qシフト演算を用いた変換

シフト演算を用いて、データを変換したいのです。

例えば、「00 01 0B 0A」となっているデータを、「0A 0B 01 00」となるようにシフト演算を用いて、変換したいのです。
0Aで1byteとなっていて、1byteごとにデータを格納して入れ替えるなど、方法は考えてみたのですが、実際のプログラムがさっぱり思いつきません。

ヒントだけでもいいので、教えていただけると嬉しいです。
すみませんが、よろしくお願いします。

Aベストアンサー

リトルエンディアンからビッグエンディアンまたはビッグエンディアンからリトルエンディアンへの変換ですね。

シフト演算子を使って計算するのであれば、ビット演算子を使えば実現できますね。

例えば、C言語風に書けば

i = 0x00010b0a ;
i = i<<24 | i<<8 & 0x00ff0000 | i>>8 & 0x0000ff00 | i>>24 & 0x000000ff ;

で出来ていると思います。
演算子の優先順位があるので、言語が違えば答えが変わってしまう可能性もありますので、

i = (i<<24) | ((i<<8) & 0x00ff0000) | ((i>>8) & 0x0000ff00) | ((i>>24) & 0x000000ff) ;

の様に括弧でくくる必要があるかもしれません。

Qアセンブラの擬似命令について

kigin と申します。
アセンブラの擬似命令に「align」というものがありますがこれは一体どういう意味なのでしょうか?
また、アセンブラの擬似命令やアセンブラプログラミングに関して詳しいガイダンス的な紹介がなされているホームページ等がありましたら、教えていただきたいのですが。
よろしくお願いいたします。

Aベストアンサー

CPUによっては2バイト分を読み書きしたりする(ワードアクセス)のときは
アドレスは偶数アドレスでなければならないとかあるCPUがあってそのときに
align 2としてもしそのデータがそのまま奇数アドレスにおくこと
になりそうなときにちゃんとダミーデータをおいて偶数アドレスから
はじめてくれるものです。

良く使うのはIntel系CPUは2バイト境界がいいとか4バイト境界が早いとかで
やります

Qアセンブリの論理演算命令のCPL(対応するbit反転)

アセンブリの論理演算命令の1つで、対応するbitを反転するCPLとは何の略称なのでしょうか?
反転は英訳するとreversalになると思うのですが、ニーモニックがCPLとなる理由が解らなくて質問しました。御存知の方がいましたら回答をお願いします。

Aベストアンサー

ComPLementの略で1の補数って意味だと思います。

Q[GNUインラインアセンブラ] SIMD命令

下記のようなGNUインラインアセンブラを含むプログラムをMac Book Airにてgccでコンパイルして実行するとPSUBSW命令は、mm0 - mm1の結果がmm0に入りますが、IntelのDevelopper's manualのPSUBSW命令の説明においては、mm1-mm0の結果がmm1に入るとなっています。

これは、なぜなのでしょうか。

---- Begin source code -----
1 #include <stdio.h>

2

3 int

4 main()

5 {

6 short int a[4] = {1111,1112,1113,1114};

7 short int b[4] = {1111,2112,3113,4114};

8 short int c[4];

9

10 asm volatile (

11 "movq (%1),%%mm0\n\t"

12 "movq (%2),%%mm1\n\t"

13 "psubsw %%mm1,%%mm0\n\t"

14 "movq %%mm0,%0\n\t"

15 "emms"

16 : "=g"(c): "r"(&a),"r"(&b));

17

18 printf("%d %d %d %d\n", c[0], c[1], c[2], c[3]);

19

20 return 0;

21 }
---- End source code -----

Intel developper's manual (http://www.intel.co.jp/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf)

PSUBSW mm, mm/m64
Subtract signed packed words in mm/m64 from signed packed words in mm and saturate results.

下記のようなGNUインラインアセンブラを含むプログラムをMac Book Airにてgccでコンパイルして実行するとPSUBSW命令は、mm0 - mm1の結果がmm0に入りますが、IntelのDevelopper's manualのPSUBSW命令の説明においては、mm1-mm0の結果がmm1に入るとなっています。

これは、なぜなのでしょうか。

---- Begin source code -----
1 #include <stdio.h>

2

3 int

4 main()

5 {

6 short int a[4] = {1111,1112,1113,1114};

7 short int b[4] = {1111,2112,3113,4114};

8 short int c[4];

...続きを読む

Aベストアンサー

詳しくないのですが、アセンブラの書式にはAT&T式とIntel式があり、オペランドのソースとデスティネーションが逆のようです。

QPrivate Sub内でSubをCallしたい

Excel 2007でVBAを組もうとしています。

ユーザーフォームのコマンドボタンをクリックすると動く処理を
Private Sub 内に書きましたが、処理が長くなりましたので、
Subに分けたいと思います。

Private subからSubプロシージャをCallすることはできますか?

またどのSubでも同じ変数を使う場合、定義は、各Sub内で
毎回行う必要がありますか?

引数渡しのところがよく分からないので、すみませんが
よろしくお願い致します。

Aベストアンサー

こちらが参考になるでしょう

Excelでお仕事
プロシージャ間の変数の受け渡し(その2)
http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_200_100.html

変数のスコープはこちらを参考に

エクセルVBA講座「変数のすべて」
第5回 変数の適用範囲(スコープ)
http://pc.nikkeibp.co.jp/pc21/special/2007_gosa/eg5.shtml


またCallは省略することもできます

Office TANAKA
Callステートメント
http://officetanaka.net/excel/vba/statement/Call.htm

Q8086アセンブラで、メモリ間のデータをストリング命令でブロック転送したい

ソースが長めなので、簡潔に書きます。ご無礼の段、ご容赦ください。
【目的】PC-9801本体のCバス(汎用拡張スロット)に挿したサウンドボード上の
ROM BIOSを読み出し、バイナリファイルに落としたい。既にエミュレータ用に実機からの
吸出しツールは存在するが、ソースが無いので、自作することにした。
その前段階としてアセンブラの修行も兼ねて、ROM BIOSの先頭3ワード(6バイト)を
メモリ上のバッファにコピーし、比較して値の合致を確認したい。
将来的にはSCSI ROM BIOSの解析等を試みたい。

【方針】8086のストリング命令でダイレクトにメモリtoメモリでブロック転送を
する。具体的にはrep movsbを用い、6バイトを転送する。

【備考】PC-9801-26K互換音源のROM BIOS(少なくとも先頭8バイト)は一意であり、
その並びは、0001h, 0000h, 00d2h である。例外はありません。
86音源でも同様で、下位互換性があることは、拙作ツール(OPNCHK.COM)にて確認済み。
なお、上記バイト列は、セグメントCC000h:オフセット2E00hから読み出し
可能である。
なお実行にあたり、所謂メモリマネージャの類(MELEMM.386等)は一切
組み込まない状態で行なう(EMSメモリマネージャ等との同居対応は将来の課題とします)。

【開発環境】PC-9801DA2(Cyrix Cx486DLC-25MHzに載せ換え; 13.6MB RAM; HA-55BS4 SCSIボード
+ 240MB SCSI HDD + SONY CPD-17SF9 CRT
+ NASM 2.06rc10 on NEC DOS 5.0A-H + Turbo Debugger v3.2 と、
秋葉で買ったジャンクFDに入ってたMASM ver 3.00;
予備機 VX41/RS21/EPSON 286VF/EPSON 486HX2/Xv13R16[K6-2 400MHz]/
AT互換機上のNekoIIエミュ/Cygwin上のnasmw.exe)

【参考書】PC-98、8086アセンブラ、テクニカルデータ、古雑誌等 定番本100冊ほど

【拙作コードの失敗点をご指南いただきたい。NASMコードですが、MASM/TASMでも構いません】
; PC-9801-26K compatible Sound ROM BIOS Copy Program (i/o address 0188h)
; Programmed by OrzHacker666
; Date 2009-07-13 for NASM 2.06rc10

[Bits 16]
org 100h ; COM program
section .text
start:
push es ; これを保存しないと、
push ds ; 画面がめちゃくちゃになる

mov ax, 0cc00h ; Sound ROM セグメントアドレス
mov es, ax
mov ds, ax ; DS:SI -> ES:DI 無意味か?
mov bx, 2e00h ; Sound ROM オフセットアドレス

lea si, [es:bx] ; ES:BX がSound ROMの開始点
lea di, [ds:sbuff] ; sbuffは仮に確保したバッファ。
; どこにあるかは、当たり前ですが、不明。そこら辺はCの変数宣言と同じですが。

mov cx, 8 ; とりあえず、アタマ8バイトをコピー
cld
rep movsb

CompareWithOriginal:
cmp word [es:bx+4], 00d2h ; これは通る。当たり前。
jne FailedCpyRom
cmp word [ds:sbuff+4], 00d2h ; ここで失敗判定。なぜ?
jne FailedCpyRom
; sbuffにes:bx~が正しく
; 転送されていないのか?
SuccessCpyRom: ; これを拝めれば…。
pop ds
pop es
mov ah, 9
lea dx, [SUCCESSMsg]
int 21h
mov ax, 4c00h
int 21h

FailedCpyRom: ; 見飽きましたOrz
pop ds
pop es
mov ah, 9
lea dx, [FAILEDMsg]
int 21h
mov ax, 4c00h
int 21h

section .data
SUCCESSMsg:
db 'Succeeded !!', 0dh, 0ah, '$'
FAILEDMsg:
db 'Failed(--;)', 0dh, 0ah, '$'

section .bss
sbuff:
resb 8 ; Cで書くと、差し詰め unsigned char sbuff[8]; であろうか…。

識者の方、よろしくお願いいたします。気になって夜も眠れません。

ソースが長めなので、簡潔に書きます。ご無礼の段、ご容赦ください。
【目的】PC-9801本体のCバス(汎用拡張スロット)に挿したサウンドボード上の
ROM BIOSを読み出し、バイナリファイルに落としたい。既にエミュレータ用に実機からの
吸出しツールは存在するが、ソースが無いので、自作することにした。
その前段階としてアセンブラの修行も兼ねて、ROM BIOSの先頭3ワード(6バイト)を
メモリ上のバッファにコピーし、比較して値の合致を確認したい。
将来的にはSCSI ROM BIOSの解析等を試みたい。

【方針...続きを読む

Aベストアンサー

>回答中の、"cmp word es:[di-4], 00D2h"は
MOVSD×2でDIはsbuff+8を指しています。DI-4はsbuff+4のことです。
これくらいはアセンブラをやる以上、直ぐに分かってください。

>sbuff自体については、セグメント値は不定で、調べる意義は無い
ちょっと乱暴な話ですね。sbuffはbss(初期値なし静的領域)のよう
なので、実行時のDSです。

確実なのはtextセグメント(コードと同じ)に次のようにデータを
定義して使います。
LES  DI,CS:adr 'ES:DIにsbuffのセグメント:オフセットが入る
== 中略 ==
adr  DD sbuff 'sbuffのセグメント:オフセットが記録される

>DS=ESではダメです
だって、そうなっていますよ。AXをDSにもESにもMOVしてます。
前にも書いたんですが、セグメントの使い方が分かっていない?

前のサンプルは上記仮定(sbuffは実行時DSにある)で作っています。
PUSH DS、POP ES ES←DSにしています。(受け取り側が実行時DS)
この後で、DSに0CC00hを代入しています。

>[es:]のオーバーライドは必須です
CMP   WORD ES:[DI-4],00D2h
ちゃんと、ESでオーバライドしてるはずですけどね。

>ジレンマに陥ります
どこがでしょう?アセンブラで、セグメントレジスタを使う以上は
自分の自由に使えば良い訳で、適当に値を設定したり、戻したりすれば
済む話なのでは?
例:
REP  MOVSB
PUSH  DS
PUSH  ES
POP   DS
POP   ES
後の4命令で、DSは実行時DSに戻り、ESはROMセグメントを指します。
サンプルではこれをやっていないので、実行時DSはESにある状態です。
故にセグメントオーバーライドしています。

>回答中の、"cmp word es:[di-4], 00D2h"は
MOVSD×2でDIはsbuff+8を指しています。DI-4はsbuff+4のことです。
これくらいはアセンブラをやる以上、直ぐに分かってください。

>sbuff自体については、セグメント値は不定で、調べる意義は無い
ちょっと乱暴な話ですね。sbuffはbss(初期値なし静的領域)のよう
なので、実行時のDSです。

確実なのはtextセグメント(コードと同じ)に次のようにデータを
定義して使います。
LES  DI,CS:adr 'ES:DIにsbuffのセグメント:オフセットが入る
== 中略 ==
...続きを読む

Q四則演算と比較演算を行う式を定義する生成規則

一桁の数値と四則演算だけを記述できる簡単な文法
の生成規則

expr -> expr + term | expr - term | term
term -> term * factor | term / factor | factor
factor -> 0 | 1 | ... | 9 | (factor)

に、関係演算子 > と < を追加したとき、
どのような生成規則になりますか?

型という観点から考えると、bool型という概念が
新たに追加されることになり、2つの関係演算子は、
bool型同士の計算はできません。
ここの、bool型同士の計算ができない、という点が、
生成規則に反映されるのか、また、
bool型同士も計算できるような生成規則を作成し、
型検査は別に行うべきなのか、
そこのところが知りたいです。

よろしくお願いします。

Aベストアンサー

一日たって読み返すと自分の書いたこと最悪ですね。

まず、
>ただし、もう一階層うえに
>rel-exp2: rel-exp |
>rel-exp < rel-exp |
>rel-exp > rel-exp
>のようなものが必要になる(そうしないと自由度が低い)かと思います。
は、自分でも何を言っているのかわかりません;;
第一、書いたことと矛盾していますね。

「<」と「>」は真理値との演算できないので、「rel-exp」と「rel-exp」の比較できないですもんね。
ま、or演算やand演算の事指していたと思ってください・・・。(逃げです;;)
混乱させて申し訳ありません。

適当に書いていると恥ずかしい思いしますねぇ^^;

回答に対する補足の説明は大筋liar_adanさんと同じ考えです。
liar_adanさん、すごいですねぇ。

ただ、大体おわかりのことかと思いますが、
言語は、扱えるデータ、およびその構造とそれを操るための文法により構成されており、
どのようなデータ構造を扱わせるか、
またそれらデータ構造に対しどのような操作を行うかは、
全てポリシーにより決定されるかと思います。
そこから、実現の仕方の違いは、単純なポリシーの違いと捕らえてよいのではないでしょうか。

C言語の場合、メモリを直接操作することが主となる
(「基本的にどれも「値」」と書かれている主な理由になるかと思います)のに対し、
Javaの場合、元となる言語がインタプリタ上での動作であり、
純粋にデータ構造を操作することが主となる
(実行効率のためにプリミティブな型がベースにありますが)、
という言語の目的の違いもあるかとは思います。
これもまぁ、ポリシーですけどね。


あと、蛇足ですが、
liar_adanさんも解って書いてらっしゃると思いますが、
生成規則では型チェックは出来ません。
あくまで、型チェックは
「字句解析->構文解析->意味解析」
の意味解析の段階で行われるものです。

たとえば、日本語の文法でも、
「人間は猫である」という文は文法上はおかしくないですよね。

ただし、在るひとつの文法に出現する方に縛りをかけることは可能であり、
それにより、一部の型チェックを省くことは出来るかと思います。
「生成規則に型チェックを任せる」
というのはそういうことを言いたいのだと思います。

今回のお題を例にとれば、日本語で真理値のTRUEと数字を比較する際、
「1はTRUEよりも大きい」とする事も文法上は可能ですが、
「数字は数字同士でなければ比較できない」という縛りをかけることで、
「1はTRUEより・・・」とした時、数字とほかのものを比較することになり、
先ほどの縛りのため、出来なくなります。

Harryさんのお書きになった、
rel_expr -> fund_expr < fund_expr |
       fund_expr > fund_expr
なども、その一例だと思います。

厳密には「数字」の意味がわからなければいけず、
かりにTRUEを数字のひとつとした場合は、可能になってしまいますが。

「型検査は別に行うべきなのか」から、ご理解されているとは思いますが、
念のためと、これを読むほかの方のためにも・・・って、読む人いるのか疑問が。

こんなことを書くのは、自分のおさらいのためだったりします^^

そうそう、一番初めの問いに対する回答って出てないんですね。
個人的な意見としては、きれいな実装を望まれるようであれば、
意味解析が必要になりますが、
「bool型同士も計算できるような生成規則を作成」を選ばれたらよいのでは、と思います。
ただ、扱う演算が現状四則演算のみであり、
そのような実装を求められているわけでもないかと思いますので、
現実解としては
「bool型同士の計算ができないという点が生成規則に反映される」形でよいのでは。

一日たって読み返すと自分の書いたこと最悪ですね。

まず、
>ただし、もう一階層うえに
>rel-exp2: rel-exp |
>rel-exp < rel-exp |
>rel-exp > rel-exp
>のようなものが必要になる(そうしないと自由度が低い)かと思います。
は、自分でも何を言っているのかわかりません;;
第一、書いたことと矛盾していますね。

「<」と「>」は真理値との演算できないので、「rel-exp」と「rel-exp」の比較できないですもんね。
ま、or演算やand演算の事指していたと思ってください・・・。(逃げです;;)
混乱...続きを読む

Q自分でアセンブラ言語を作れる?

自分でアセンブラ言語を作れる?
あるCPUにmov命令というのがありますが命令名をソフトウェアレベルで変えることは
出来るのでしょうか?
(mov ax,1をmove ax,1にしたり)
アセンブラはCPUが同じならどれも同じだと思っていたのですが
プログラムを終了する時、windowsはint 21hなのにlinuxはint 0x80なので
疑問に思いました。

Aベストアンサー

> windowsはint 21hなのにlinuxはint 0x80なので
これはアセンブリ言語の問題ではなくAPIの問題です。
intはソフトウエア割り込み命令でBIOSやAPIを呼び出すのに使います。
同じような機能でもWindowsやLinuxなどのOSが違えば呼び出しアドレスが違うのは当然です。

> アセンブラはCPUが同じならどれも同じだと思っていたのですが
アセンブリ言語のニーモニクはCPUメーカーが同じなら同じです。
が、CPU毎に同じなのはマシン語であってアセンブリ言語のニーモニクではありません。
例えばインテル8080とザイログZ80はマシン語レベルで高い互換性がありますがアセンブリ言語のニーモニクは大きく異なります。
最終的にマシン語コードが出来上がればニーモニクはmov ax,1でもmove ax,1でもax=1でも関係ありません。

Q正数分割の個数

最近、組み分けの問題を考える機会があって、
アルゴリズム辞典を見てみると、「正数分割の個数」(同じ問題と言える)を求めるプログラム(元はPascal)があったのですが、正直言ってなぜこれで求めることができるのか理解できませんでした。
どうしてこのプログラムで、件数を求めることができるのか教えてください。
プログラムは、以下のようなもの(C言語で書き直したもの)
/*
ある正数nを分割する(正数の和で表す表し方の)数を求める

4:4,1+3,2+2,1+1+2,1+1+1の5通り
partition(4,4)→5
*/
int partition(int n, int k){
 int p,i;
 if(n<0) return 0;
 if(n<2 || k==1) return 1;
 for(p=0,i=1;i<=k;i++){
  p+=partition(n-i,i);
 }
 return p;
}

Aベストアンサー

失礼しました。
#3で紹介した式を証明します。

・p(n,k)=q(n,1)+q(n,2)+・・・+q(n,k)
pの定義から左辺は項数がk以下のnの分割、従って、
項数が1の分割の個数+・・・+項数がkの分割の個数
であり、これはqの定義から右辺に等しい。

・q(n,k)=p(n-k,k) 
αを項数kのnの分割とする。各項から、1を引くと
項数がk以下のn-kの分割βが得られる。(αが1の項を含めば、βの項数はαより少なくなることに注意)
逆に、項数がk以下のn-kの分割βに対し各項に1を加える
(但し、βの項数がkに満たなければ、足りない分だけ1の項を追加する)と、項数kのnの分割が得られる。
従って、項数kのnの分割と項数がk以下のn-kの分割とは
一対一に対応する。


このカテゴリの人気Q&Aランキング

おすすめ情報