những opcode cơ bản
***********
NHỮNG OPCODE CƠ BẢN CẦN PHẢI HIỂU
*****************
* các phần của file class: file class gồm có nhiều thông tin, nhưng khi thực hiện trên bytecode chỉ cần biết nó có các phần sau:
- constant pools: (bảng hằng) cũng không rõ nó dịch ra tiếng Việt là gì thì sẽ chính xác hơn, nhưng rõ ràng nó là những hằng số. thứ tự của mỗi hằng số chính là index của nó, và trong class sẽ sử dụng nó để tạo thành cấu trúc file, có những hằng số được tạo ra bằng cách ghép các hằng số có giá trị khác lại. index bắt đầu từ 1, index 0 không được sử dụng vì nó làm lẫn lộn với opcode null. giống như thế này:
....
0 null
1 a
2 m
3 ()V
4 "day la chuoi"
........
- field: các trường hay biến trong class, được sử dụng trong các hàm, mỗi field này có dạng
[truy xuất] [tên] [kiểu]
phần kiểu này có chủ yếu mấy dạng sau:
B kiểu byte số có giá trị từ -127 đến 127
C kiểu char kí tự, có giá trị 0 đến 127
D kiểu double, số thực
F kiểu float, số thực
I kiểu int, số nguyên lớn hơn byte
J kiểu long, số nguyên lớn hơn int
S kiểu short, số nguyên lớn hơn int, nhỏ hơn long
Z kiểu đúng sai, chỉ mang 2 gí trị, 0, 1
L[x]; kiểu load class, [x] là tên class, bắt đầu bằng chữ "L" và kết thúc tại ";"
[[kiểu] kiểu array, bắt đầu bằng "[", phần kiểu là các kiểu trên.
vd: public a I có nghĩa là field tên a, kiểu int.
private b Lh; có nghĩa là field tên b, được tạo ra từ load class h.
- method: hàm, là nơi chứa các code thực thi chương trình.
[truy xuất] [tên] ([tham số]) [kiểu]
phần kiểu ngoài những kiểu như của field thì còn có kiểu void V, kiểu V là kiểu chỉ thực thi mà ko trả lại gì cả.
vd: private meme (ILf;)V có nghĩa là hàm tên meme, cần dùng tham số kiểu int, và tham số kiểu class f, kiểu trả lại là thực thi V.
- code trong method là tập hợp những phần tử bắt đầu bằng opcode và giá trị theo sau của từng opcode, vì có hơn 100 opcode nên sẽ không được nói chi tiết ở đây. chỉ cần biết là mỗi opcode là 1 số có index nhất định và có cấu trúc của nó, có opcode chỉ đứng 1 mình, có opcode cần có giá trị theo sau, giá trị đi trước. những giá trị này được lấy từ bảng hằng constant pool lúc nãy đã nói.
vd:
......
iconst_0 ->là opcode đưa ra số 0, nó ko cần có gì trước sau hết.
ireturn ->là opcode trả về 1 số nguyên, vậy trước nó phải có 1 số nguyên.
ldc "đây là chuỗi" ->ldc là opcode dẫn ra 1 chuỗi hoặc 1 số, nó buộc sau nó phải là 1 index dẫn đến 1 chuỗi trong bảng hằng.
getfield a/f I -> getfield là opcode lấy giá trị từ trường trong class, phía trước nó phải có 1 class, sau nó là "a/f I" chỉ ra tên class, tên biến và kiểu biến được lấy.
invokevirtual a/meme()I -> invokevirtual là opcode thực hiện hàm, trước nó cần có đủ class chứa hàm, các tham số cần thực hiện hàm, phía sau là tên class, tên hàm, tham số và kiểu trả về của hàm.
invokestatic b/bebe(I)V ->invokestatic là opcode thực hiện hàm static, trước nó chỉ cần đủ tham số, không cần class để thực hiện hàm, phía sau vẫn giống như hàm thông thường, gồm tên class, tên hàm, tham số, kiểu trả về.
if_icmplt label10 ->if_icmplt là opcode điều kiện so sánh 2 số nguyên, vì vậy nó cần có 2 giá trị số nguyên phía trước, sau nó là 1 số, chỉ ra nơi sẽ chuyển đến khi điều kiện đúng.
goto label67 ->goto là opcode chuyển đến 1 điểm trong code để tiếp tục thực thi, trước nó chẳng cần gì, sau nó phải là 1 số chỉ ra điểm tiếp tục trong code.
......
* khi chỉnh sửa code bằng bytecode mobile:
nếu bạn chỉnh sửa giá trị trong constant pools thì tất cả các code có lấy giá trị từ nó đều thay đổi theo, vì nó là khởi nguồn của tất cả.
vd: trong bảng hằng có giá trị chuỗi là "con khỉ", giá trị này được sử dụng trong method a và method b, thì khi bạn sửa trong bảng hằng thì cả a và b đều thay đổi.
nếu bạn chỉnh sửa giá trị trong code của hàm thì constant pool sẽ được thêm những giá trị mới, và chỉ có hàm đó được thay giá trị, những hàm khác sử dụng cùng giá trị không bị thay đổi.
vd: như ví dụ trên, nếu bạn mở hàm a ra và chỉnh lại ->ldc "con khỉ" <- thì bảng hằng sẽ thêm vài giá trị mới, và giá trị "con khỉ" trong b không bị thay đổi.
* iconst_0, iconst_1, iconst_2, iconst_3, iconst_4, iconst_5 là giá trị từ 0 đến 5 sau code này phải có 1 code dùng giá trị nguyên này.
* bipush [x] là đưa ra giá trị số nguyên, [x] là 1 số nguyên, sau code này phải có 1 code dùng giá trị nguyên này.
* sipush [x] cũng đưa ra 1 số nguyên, [x] là 1 số nguyên, sau code này phải có 1 code dùng giá trị nguyên này.
* ldc [....] dùng để đưa ra chuỗi hoặc số, sau code này phải có 1 code dùng giá trị này.
* getfield [...], getstatic [....] dùng để lấy 1 giá trị trong một class nào đó, trước getfield phải có giá trị class, sau code này phải có 1 code dùng giá trị này.
* goto [x], goto_w [x] dùng để chuyển đến 1 vị trí nào đó trong code, hãy tưởng tượng code là là 1 dãy gồm nhiều ô, ghép lại thành 1 hàng dài, [x] là chính là vị trí cần đến.
* if[...] [x] có nhiều loại if, trước if phải có giá trị để so sánh, nếu là if_[...] thì cần 2 giá trị, if[...] cần 1 giá trị thôi vì so sánh với 0 hoặc null. [x] là điểm cần đi đến nếu điều kiện so sánh đúng, nếu ko đúng thì tiếp tục thực hiện code.
* [x]load và [x]store và [x]return : load tức nhiên là lấy giá trị, store là gán giá trị, và return là trả về, nó mang tính tức thời giống như tải giá trị vào bộ nhớ ram rồi sử dụng, sử dụng xong thì giải phóng. load và store ta thấy suốt trong code, còn return thì là nơi code sẽ kết thúc thực thi. load và store đều có theo sau bởi 1 vị trí, đó là vị trí lưu trữ, mặc định vị trí lưu trữ 0 là class đang thực thi hàm này, trừ static method vị trí 0 vẫn trống. trước khi load phải store, trước store phải có giá trị, sau load phải có code nhận giá trị.
trong đó x có thể là 1 trong số những giá trị này:
iinteger
llong
sshort
bbyte
cchar
ffloat
ddouble
zboolean, đúng sai
areference, load class
tùy vào kiểu của method mà [x]return sẽ thuộc vào 1 trong các giá trị sau: nếu là số thì dùng d, i, l, f, nếu là load class, array thì dùng areturn, nếu là boolean đúng sai thì dùng ireturn.
* [x]aload và [x]astore : cũng giống như ở trên, nhưng đây là dùng cho array, lấy và gán giá trị cho 1 phần tử trong array.
* nop và pop: nop là opcode null, giá trị của nó là 0, nó chẳng làm gì cả, nhưng nếu nó chen ngang những thành phần của opcode khác sẽ gây lỗi, pop là loại bỏ giá trị đưa ra, trước pop phải có 1 giá trị, ví dụ:
-> invokestatic f/h()I
pop <-như vậy giá trị int được trả lại từ method sẽ bị loại bỏ, ko sử dụng nó.
* [x]add, [x]sub, [x]mul và [x]div : là các hàm tính toán có sẵn add là cộng, sub là trừ, mul là nhân, div là chia. trước nó phải có 2 giá trị để được thực hiện, sau nó phải có 1 code nhận giá trị này.
->iconts_4
bipush 7
iadd
istore_1 <-cộng 4 với 7 và lưu vào vị trí 1.
một ví dụ:
->
iload_2 //tải số nguyên lưu tại vị trí 2
iload_3 //tải số nguyên lưu tại vị trí 3
ineg //đổi dấu số đằng trước nó, ở đây là số lưu tại 3, trả về số nguyên âm.
invokestatic bk/a(II)I //nhận số lưu tại 2, và số âm lưu tại 3 và thực hiện hàm, trả lại số nguyên.
istore_2 //lưu số nguyên do hàm trả ra vào vị trí 2
iconst_0 //đưa ra 1 số 0
istore_3 //lưu số 0 vào vị trí 3
iload 4 //tải số lưu tại 4
ifeq 50 //nếu số 4 mà bằng 0 thì đi tới vị trí code 50.
<-
end.
.:viết bởi holyeyed:.
Bạn đang đọc truyện trên: AzTruyen.Top