Add unused @F label test

This commit is contained in:
0xd4d 2020-01-26 12:11:25 +01:00
parent 91af9b6a6d
commit 3f3d15bade
3 changed files with 58 additions and 35 deletions

View File

@ -229,7 +229,7 @@ static class HowTo_Assemble {
// To broadcast memory, use the __dword_bcst/__qword_bcst memory types
c.vunpcklps(xmm2.k5.z, xmm6, __dword_bcst[rax]);
// You can create anonymous labels, just like in eg. masm @F and @B
// You can create anonymous labels, just like in eg. masm, @@, @F and @B
c.AnonymousLabel(); // same as @@: in masm
c.inc(rax);
c.je(c.@B); // reference the previous anonymous label

View File

@ -45,41 +45,41 @@ namespace Iced.UnitTests.Intel.AssemblerTests {
[Fact]
void Anonymous_labels() {
var c = new Assembler(64);
var c = new Assembler(64);
var lbl1 = c.CreateLabel();
var lbl2 = c.CreateLabel();
var lbl3 = c.CreateLabel();
var lbl4 = c.CreateLabel();
var lbl1 = c.CreateLabel();
var lbl2 = c.CreateLabel();
var lbl3 = c.CreateLabel();
var lbl4 = c.CreateLabel();
c.Label(ref lbl1);
c.inc(eax);
c.nop();
c.AnonymousLabel();
c.je(c.@B);
c.nop();
c.Label(ref lbl2);
c.je(c.@B);
c.nop();
c.jmp(lbl1);
c.nop();
c.jmp(lbl2);
c.nop();
c.jmp(lbl3);
c.nop();
c.jmp(lbl4);
c.nop();
c.jne(c.@F);
c.nop();
c.Label(ref lbl3);
c.jne(c.@F);
c.nop();
c.AnonymousLabel();
c.inc(eax);
c.nop();
c.Label(ref lbl4);
c.nop();
c.nop();
c.Label(ref lbl1);
c.inc(eax);
c.nop();
c.AnonymousLabel();
c.je(c.@B);
c.nop();
c.Label(ref lbl2);
c.je(c.@B);
c.nop();
c.jmp(lbl1);
c.nop();
c.jmp(lbl2);
c.nop();
c.jmp(lbl3);
c.nop();
c.jmp(lbl4);
c.nop();
c.jne(c.@F);
c.nop();
c.Label(ref lbl3);
c.jne(c.@F);
c.nop();
c.AnonymousLabel();
c.inc(eax);
c.nop();
c.Label(ref lbl4);
c.nop();
c.nop();
var expectedData = new byte[] {
0xFF, 0xC0, 0x90, 0x74, 0xFE, 0x90, 0x74, 0xFB, 0x90, 0xEB, 0xF5, 0x90, 0xEB, 0xF8, 0x90, 0xEB,
@ -98,6 +98,22 @@ namespace Iced.UnitTests.Intel.AssemblerTests {
Assert.Throws<InvalidOperationException>(() => c.Assemble(new CodeWriterImpl(), 0));
}
[Fact]
void Undeclared_forward_anon_label_throws() {
var c = new Assembler(64);
c.nop();
c.je(c.@F);
Assert.Throws<InvalidOperationException>(() => c.Assemble(new CodeWriterImpl(), 0));
}
[Fact]
void At_most_one_anon_label_per_instruction() {
var c = new Assembler(64);
c.nop();
c.AnonymousLabel();
Assert.Throws<InvalidOperationException>(() => c.AnonymousLabel());
}
[Fact]
void Referencing_backward_anon_label_when_not_defined_throws() {
var c = new Assembler(64);

View File

@ -127,10 +127,12 @@ namespace Iced.Intel {
}
/// <summary>
/// Creates an anonymous label that can be referenced by using the <see cref="B"/> (backward anonymous label)
/// Creates an anonymous label that can be referenced by using <see cref="B"/> (backward anonymous label)
/// and <see cref="F"/> (forward anonymous label).
/// </summary>
public void AnonymousLabel() {
if (_definedAnonLabel)
throw new InvalidOperationException("At most one anonymous label per instruction is allowed");
if (_nextAnonLabel.IsEmpty)
_currentAnonLabel = CreateLabel();
else
@ -478,6 +480,11 @@ namespace Iced.Intel {
return false;
}
if (!_nextAnonLabel.IsEmpty) {
errorMessage = "Found an @F anonymous label reference but there was no call to " + nameof(AnonymousLabel);
return false;
}
var blocks = new[] { new InstructionBlock(writer, _instructions, rip) };
if (BlockEncoder.TryEncode(Bitness, blocks, out errorMessage, out var blockResults, options)) {
assemblerResult = new AssemblerResult(blockResults);