From e240978379b937a18b782912d5a609c674faf073 Mon Sep 17 00:00:00 2001 From: Victor Date: Sat, 22 Mar 2014 18:45:13 +0200 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=BA=D0=BE=D0=B4=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/annimon/asm/directives/Add.java | 334 +++++++++--------- .../annimon/asm/directives/ByteRegister.java | 52 ++- src/com/annimon/asm/directives/ByteValue.java | 47 ++- .../annimon/asm/directives/InfinityValue.java | 50 ++- src/com/annimon/asm/directives/Register.java | 50 +-- .../annimon/asm/directives/WordRegister.java | 50 ++- src/com/annimon/asm/directives/WordValue.java | 47 ++- 7 files changed, 302 insertions(+), 328 deletions(-) diff --git a/src/com/annimon/asm/directives/Add.java b/src/com/annimon/asm/directives/Add.java index adc10d1..7bda4eb 100644 --- a/src/com/annimon/asm/directives/Add.java +++ b/src/com/annimon/asm/directives/Add.java @@ -1,167 +1,167 @@ -package com.annimon.asm.directives; - -import com.annimon.asm.ListingGenerateHelper; -import com.annimon.asm.VarTable; -import com.annimon.asm.exceptions.CommaExpectedException; -import com.annimon.asm.exceptions.ExceptionWithLineNumber; -import com.annimon.asm.exceptions.FewArgumentsException; -import com.annimon.asm.exceptions.TooManyArgumentsException; -import com.annimon.asm.exceptions.WrongArgumentException; - -/** - * - * @author aNNiMON - */ -public class Add extends Directive implements ISyntaxChecker, IListingGenerator { - - public Add() { - super("add", ID.ADD); - } - - @Override - public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { - if (ids[0] != getId()) return false; - - if (ids.length < 4) throw new FewArgumentsException(lineNumber); - else if (ids.length > 4) throw new TooManyArgumentsException(lineNumber); - - if (ids[2] != ID.COMMA) throw new CommaExpectedException(lineNumber); - - int[] pairs = new int[] { - // Регистр - Регистр - ID.REGISTER_BYTE, ID.REGISTER_BYTE, - ID.REGISTER_WORD, ID.REGISTER_WORD, - ID.REGISTER_WORD, ID.REGISTER_BYTE, - - // Регистр - Память - ID.REGISTER_BYTE, ID.VAR_BYTE, - ID.REGISTER_WORD, ID.VAR_WORD, - ID.REGISTER_WORD, ID.VAR_BYTE, - - // Память - Регистр - ID.VAR_BYTE, ID.REGISTER_BYTE, - ID.VAR_WORD, ID.REGISTER_WORD, - ID.VAR_WORD, ID.REGISTER_BYTE, - - // Регистр - Значение - ID.REGISTER_BYTE, ID.NUMBER_BYTE, - ID.REGISTER_WORD, ID.NUMBER_WORD, - ID.REGISTER_WORD, ID.NUMBER_BYTE, - - // Память - Значение - ID.VAR_BYTE, ID.NUMBER_BYTE, - ID.VAR_WORD, ID.NUMBER_WORD, - ID.VAR_WORD, ID.NUMBER_BYTE, - }; - - boolean correct = false; - for(int i = 0; i < pairs.length; i += 2) { - if ( (ids[1] == pairs[i]) && (ids[3] == pairs[i+1]) ) { - correct = true; - break; - } - } - if (!correct) throw new WrongArgumentException(lineNumber); - return true; - } - - @Override - public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { - if (ids[0] != getId()) return ""; - - StringBuilder sb = new StringBuilder(); - - if ( (ids[3] == ID.NUMBER_BYTE) || (ids[3] == ID.NUMBER_WORD) ) { - - // ADD acc, imm 0000010w | data - if ( (strs[1].equalsIgnoreCase("ax")) || (strs[1].equalsIgnoreCase("al")) ) { - byte val = 0b00000100; - if (strs[1].equalsIgnoreCase("ax")) val |= 1; - - sb.append(ListingGenerateHelper.toHexString(val)) - .append(' ') - .append(ListingGenerateHelper.toLittleEndianString(strs[3])); - return sb.toString(); - } - - // ADD r/m, imm 100000sw | mod000r/m | data - if (ListingGenerateHelper.isRegisterOrMemory(ids[1])) { - int val = 0b100000_00; - if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { - val |= 1; - } - - String varaddr = " "; - if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { - short offset = vars.getAddressOfVariable(strs[1]); - varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; - } - - // mod - int modreg = 0b00; - if (ids[1] == ID.REGISTER_WORD) modreg = 0b11; - modreg <<= 6; - - // r/m - if (strs[1].toLowerCase().indexOf("si") != -1) modreg |= 0b100; - else if (strs[1].toLowerCase().indexOf("di") != -1) modreg |= 0b101; - else modreg |= 0b110; - - sb.append(ListingGenerateHelper.toHexString(val)) - .append(' ') - .append(ListingGenerateHelper.toHexString(modreg)) - .append(varaddr) - .append(ListingGenerateHelper.toLittleEndianString(strs[3])); - return sb.toString(); - } - } - - // ADD r/m, reg 000000dw | modregr/m - if (ListingGenerateHelper.isRegisterOrMemory(ids[1])) { - int val = 0b000000_00; - if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { - val |= 1; - } - if ( (ids[1] == ID.REGISTER_BYTE) || (ids[1] == ID.REGISTER_WORD) ) { - val |= 0b10; - } - - String varaddr = " "; - if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { - short offset = vars.getAddressOfVariable(strs[1]); - varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; - } - - // mod - int modreg = 0b00; - if ( (ListingGenerateHelper.isRegister(ids[1])) && - (ListingGenerateHelper.isRegister(ids[3])) ) { - // Если оба операнда - регистры, то mod = 11 - modreg |= 0b11; - } - modreg <<= 6; - - // r/m - if (modreg == 0) modreg = 0b110; - else { - // Если mod != 11, то r/m - id регистра. - modreg |= ListingGenerateHelper.getRegisterCode(strs[3]); - } - - // reg - id регистра первого операнда, либо 0. - byte regID = ListingGenerateHelper.getRegisterCode(strs[1]); - if (modreg == 0b110) { - regID = ListingGenerateHelper.getRegisterCode(strs[3]); - } - regID <<= 3; - modreg |= regID; - - sb.append(ListingGenerateHelper.toHexString(val)) - .append(' ') - .append(ListingGenerateHelper.toHexString(modreg)) - .append(varaddr); - } - - return sb.toString(); - } -} +package com.annimon.asm.directives; + +import com.annimon.asm.ListingGenerateHelper; +import com.annimon.asm.VarTable; +import com.annimon.asm.exceptions.CommaExpectedException; +import com.annimon.asm.exceptions.ExceptionWithLineNumber; +import com.annimon.asm.exceptions.FewArgumentsException; +import com.annimon.asm.exceptions.TooManyArgumentsException; +import com.annimon.asm.exceptions.WrongArgumentException; + +/** + * + * @author aNNiMON + */ +public class Add extends Directive implements ISyntaxChecker, IListingGenerator { + + public Add() { + super("add", ID.ADD); + } + + @Override + public boolean check(int lineNumber, int[] ids) throws ExceptionWithLineNumber { + if (ids[0] != getId()) return false; + + if (ids.length < 4) throw new FewArgumentsException(lineNumber); + else if (ids.length > 4) throw new TooManyArgumentsException(lineNumber); + + if (ids[2] != ID.COMMA) throw new CommaExpectedException(lineNumber); + + int[] pairs = new int[] { + // Регистр - Регистр + ID.REGISTER_BYTE, ID.REGISTER_BYTE, + ID.REGISTER_WORD, ID.REGISTER_WORD, + ID.REGISTER_WORD, ID.REGISTER_BYTE, + + // Регистр - Память + ID.REGISTER_BYTE, ID.VAR_BYTE, + ID.REGISTER_WORD, ID.VAR_WORD, + ID.REGISTER_WORD, ID.VAR_BYTE, + + // Память - Регистр + ID.VAR_BYTE, ID.REGISTER_BYTE, + ID.VAR_WORD, ID.REGISTER_WORD, + ID.VAR_WORD, ID.REGISTER_BYTE, + + // Регистр - Значение + ID.REGISTER_BYTE, ID.NUMBER_BYTE, + ID.REGISTER_WORD, ID.NUMBER_WORD, + ID.REGISTER_WORD, ID.NUMBER_BYTE, + + // Память - Значение + ID.VAR_BYTE, ID.NUMBER_BYTE, + ID.VAR_WORD, ID.NUMBER_WORD, + ID.VAR_WORD, ID.NUMBER_BYTE, + }; + + boolean correct = false; + for(int i = 0; i < pairs.length; i += 2) { + if ( (ids[1] == pairs[i]) && (ids[3] == pairs[i+1]) ) { + correct = true; + break; + } + } + if (!correct) throw new WrongArgumentException(lineNumber); + return true; + } + + @Override + public String generate(int lineNumber, int[] ids, String[] strs, VarTable vars) { + if (ids[0] != getId()) return ""; + + StringBuilder sb = new StringBuilder(); + + if ( (ids[3] == ID.NUMBER_BYTE) || (ids[3] == ID.NUMBER_WORD) ) { + + // ADD acc, imm 0000010w | data + if ( (strs[1].equalsIgnoreCase("ax")) || (strs[1].equalsIgnoreCase("al")) ) { + byte val = 0b00000100; + if (strs[1].equalsIgnoreCase("ax")) val |= 1; + + sb.append(ListingGenerateHelper.toHexString(val)) + .append(' ') + .append(ListingGenerateHelper.toLittleEndianString(strs[3])); + return sb.toString(); + } + + // ADD r/m, imm 100000sw | mod000r/m | data + if (ListingGenerateHelper.isRegisterOrMemory(ids[1])) { + int val = 0b100000_00; + if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { + val |= 1; + } + + String varaddr = " "; + if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { + short offset = vars.getAddressOfVariable(strs[1]); + varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; + } + + // mod + int modreg = 0b00; + if (ids[1] == ID.REGISTER_WORD) modreg = 0b11; + modreg <<= 6; + + // r/m + if (strs[1].toLowerCase().contains("si")) modreg |= 0b100; + else if (strs[1].toLowerCase().contains("di")) modreg |= 0b101; + else modreg |= 0b110; + + sb.append(ListingGenerateHelper.toHexString(val)) + .append(' ') + .append(ListingGenerateHelper.toHexString(modreg)) + .append(varaddr) + .append(ListingGenerateHelper.toLittleEndianString(strs[3])); + return sb.toString(); + } + } + + // ADD r/m, reg 000000dw | modregr/m + if (ListingGenerateHelper.isRegisterOrMemory(ids[1])) { + int val = 0b000000_00; + if ( (ids[1] == ID.REGISTER_WORD) || (ids[1] == ID.VAR_WORD) ) { + val |= 1; + } + if ( (ids[1] == ID.REGISTER_BYTE) || (ids[1] == ID.REGISTER_WORD) ) { + val |= 0b10; + } + + String varaddr = " "; + if ( (ids[1] == ID.VAR_BYTE) || (ids[1] == ID.VAR_WORD)) { + short offset = vars.getAddressOfVariable(strs[1]); + varaddr += ListingGenerateHelper.toLittleEndianString(offset) + " "; + } + + // mod + int modreg = 0b00; + if ( (ListingGenerateHelper.isRegister(ids[1])) && + (ListingGenerateHelper.isRegister(ids[3])) ) { + // Если оба операнда - регистры, то mod = 11 + modreg |= 0b11; + } + modreg <<= 6; + + // r/m + if (modreg == 0) modreg = 0b110; + else { + // Если mod != 11, то r/m - id регистра. + modreg |= ListingGenerateHelper.getRegisterCode(strs[3]); + } + + // reg - id регистра первого операнда, либо 0. + byte regID = ListingGenerateHelper.getRegisterCode(strs[1]); + if (modreg == 0b110) { + regID = ListingGenerateHelper.getRegisterCode(strs[3]); + } + regID <<= 3; + modreg |= regID; + + sb.append(ListingGenerateHelper.toHexString(val)) + .append(' ') + .append(ListingGenerateHelper.toHexString(modreg)) + .append(varaddr); + } + + return sb.toString(); + } +} diff --git a/src/com/annimon/asm/directives/ByteRegister.java b/src/com/annimon/asm/directives/ByteRegister.java index 48dda50..e18e091 100644 --- a/src/com/annimon/asm/directives/ByteRegister.java +++ b/src/com/annimon/asm/directives/ByteRegister.java @@ -1,28 +1,24 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class ByteRegister extends Register { - - public ByteRegister() { - super(); - } - - @Override - public int getId() { - return ID.REGISTER_BYTE; - } - - @Override - protected String[] getRegisterNames() { - return new String[] { - "ah", "al", - "bh", "bl", - "ch", "cl", - "dh", "dl", - }; - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class ByteRegister extends Register { + + @Override + public int getId() { + return ID.REGISTER_BYTE; + } + + @Override + protected String[] getRegisterNames() { + return new String[] { + "ah", "al", + "bh", "bl", + "ch", "cl", + "dh", "dl", + }; + } + +} diff --git a/src/com/annimon/asm/directives/ByteValue.java b/src/com/annimon/asm/directives/ByteValue.java index af5c4dd..5a505c7 100644 --- a/src/com/annimon/asm/directives/ByteValue.java +++ b/src/com/annimon/asm/directives/ByteValue.java @@ -1,27 +1,20 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class ByteValue extends NumericValue { - - public ByteValue() { - super(); - } - - @Override - public int getId() { - return ID.NUMBER_BYTE; - } - - @Override - protected boolean checkRange(Integer value) { - if (value == null) return false; - if ( (-128 <= value.intValue()) && (value.intValue() <= 255) ) { - return true; - } - return false; - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class ByteValue extends NumericValue { + + @Override + public int getId() { + return ID.NUMBER_BYTE; + } + + @Override + protected boolean checkRange(Integer value) { + if (value == null) return false; + return (-128 <= value) && (value <= 255); + } + +} diff --git a/src/com/annimon/asm/directives/InfinityValue.java b/src/com/annimon/asm/directives/InfinityValue.java index 3ec59e8..d565a0c 100644 --- a/src/com/annimon/asm/directives/InfinityValue.java +++ b/src/com/annimon/asm/directives/InfinityValue.java @@ -1,27 +1,23 @@ -package com.annimon.asm.directives; - -/** - * Неопределённое значение (?) - * @author aNNiMON - */ -public class InfinityValue extends NumericValue { - - public InfinityValue() { - super(); - } - - @Override - public int getId() { - return ID.NUMBER_INFINITY; - } - - @Override - public boolean isDirective(String text) { - return text.equals("?"); - } - - @Override - protected boolean checkRange(Integer value) { - return true; - } -} +package com.annimon.asm.directives; + +/** + * Неопределённое значение (?) + * @author aNNiMON + */ +public class InfinityValue extends NumericValue { + + @Override + public int getId() { + return ID.NUMBER_INFINITY; + } + + @Override + public boolean isDirective(String text) { + return text.equals("?"); + } + + @Override + protected boolean checkRange(Integer value) { + return true; + } +} diff --git a/src/com/annimon/asm/directives/Register.java b/src/com/annimon/asm/directives/Register.java index 7e0815e..c8d8fc9 100644 --- a/src/com/annimon/asm/directives/Register.java +++ b/src/com/annimon/asm/directives/Register.java @@ -1,25 +1,25 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public abstract class Register extends Directive { - - public Register() { - super("", ID.NULL); - } - - @Override - public boolean isDirective(String text) { - String[] names = getRegisterNames(); - for (int i = 0; i < names.length; i++) { - if (text.equalsIgnoreCase(names[i])) { - return true; - } - } - return false; - } - - protected abstract String[] getRegisterNames(); -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public abstract class Register extends Directive { + + public Register() { + super("", ID.NULL); + } + + @Override + public boolean isDirective(String text) { + String[] names = getRegisterNames(); + for (String register : names) { + if (text.equalsIgnoreCase(register)) { + return true; + } + } + return false; + } + + protected abstract String[] getRegisterNames(); +} diff --git a/src/com/annimon/asm/directives/WordRegister.java b/src/com/annimon/asm/directives/WordRegister.java index 1207f3c..af03c16 100644 --- a/src/com/annimon/asm/directives/WordRegister.java +++ b/src/com/annimon/asm/directives/WordRegister.java @@ -1,27 +1,23 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class WordRegister extends Register { - - public WordRegister() { - super(); - } - - @Override - public int getId() { - return ID.REGISTER_WORD; - } - - @Override - protected String[] getRegisterNames() { - return new String[] { - "ax", "bx", "cx", "dx", - "cs", "ds", "ss", "es", - "sp", "bp", "si", "di" - }; - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class WordRegister extends Register { + + @Override + public int getId() { + return ID.REGISTER_WORD; + } + + @Override + protected String[] getRegisterNames() { + return new String[] { + "ax", "bx", "cx", "dx", + "cs", "ds", "ss", "es", + "sp", "bp", "si", "di" + }; + } + +} diff --git a/src/com/annimon/asm/directives/WordValue.java b/src/com/annimon/asm/directives/WordValue.java index cdf9f40..6496c4c 100644 --- a/src/com/annimon/asm/directives/WordValue.java +++ b/src/com/annimon/asm/directives/WordValue.java @@ -1,27 +1,20 @@ -package com.annimon.asm.directives; - -/** - * - * @author aNNiMON - */ -public class WordValue extends NumericValue { - - public WordValue() { - super(); - } - - @Override - public int getId() { - return ID.NUMBER_WORD; - } - - @Override - protected boolean checkRange(Integer value) { - if (value == null) return false; - if ( (-32768 <= value.intValue()) && (value.intValue() <= 65535) ) { - return true; - } - return false; - } - -} +package com.annimon.asm.directives; + +/** + * + * @author aNNiMON + */ +public class WordValue extends NumericValue { + + @Override + public int getId() { + return ID.NUMBER_WORD; + } + + @Override + protected boolean checkRange(Integer value) { + if (value == null) return false; + return (-32768 <= value) && (value <= 65535); + } + +}