diff --git a/src/app/transactiontest/main.cc b/src/app/transactiontest/main.cc
index e359e67a2e63a7da1db17f11968f64239987dd51..cb2d86e28e995338b47db89299077e475b1a0c18 100644
--- a/src/app/transactiontest/main.cc
+++ b/src/app/transactiontest/main.cc
@@ -8,37 +8,31 @@
 #endif
 
 extern "C" {
-	void asm_save_toc();
-	void asm_load_toc();
+	void asm_save_all();
+	void asm_load_all();
+	void asm_load_mem();
 }
 
-volatile bool __attribute__((section(".text"))) have_state = false;
 uint16_t i = 0;
 
-void restore_state()
-{
-	if (!have_state) {
-		return;
-	}
-	asm_load_toc();
-}
-
-void save_state()
-{
-	asm_save_toc();
-	have_state = true;
-}
+class Transaction {
+	public:
+		inline Transaction() { asm_save_all(); }
+		inline ~Transaction() {}
+		inline void retry() { asm_load_all(); }
+		inline void abort() { asm_load_mem(); }
+};
 
 void loop(void)
 {
 	gpio.led_toggle(1);
-	kout << dec << i << endl;
-	i++;
-	if (i == 5) {
-		save_state();
-	}
-	if (i == 10) {
-		restore_state();
+	{
+		Transaction tx;
+		kout << dec << i << endl;
+		i++;
+		if (!gpio.read(GPIO::p4_5)) {
+			tx.abort();
+		}
 	}
 }
 
@@ -48,15 +42,11 @@ int main(void)
 	gpio.setup();
 	kout.setup();
 
-	restore_state();
+	//restore_state();
 
 	gpio.led_on(0);
+	gpio.input(GPIO::p4_5, 1);
 	kout << "Hello, World!" << endl;
-	kout << "Test, World!" << endl;
-	kout << dec << uptime.get_cycles() << endl;
-	kout << dec << uptime.get_cycles() << endl;
-	kout << dec << uptime.get_cycles() << endl;
-	kout << dec << uptime.get_cycles() << endl;
 
 	arch.idle_loop();
 
diff --git a/src/app/transactiontest/util.S b/src/app/transactiontest/util.S
index bf2530d1959ce3421d2ee5e4f4ad02aef7a0d475..c0b1ebcbe459538539cbabf81b110566754b2856 100644
--- a/src/app/transactiontest/util.S
+++ b/src/app/transactiontest/util.S
@@ -1,5 +1,6 @@
-.global asm_save_toc
-.global asm_load_toc
+.global asm_save_all
+.global asm_load_all
+.global asm_load_mem
 
 stack_backup:
     .space 2048
@@ -7,7 +8,8 @@ stack_backup:
 sp_backup:
     .space 2
 
-asm_save_toc:
+asm_save_all:
+    dint
     .irp reg,4,5,6,7,8,9,10,11
     push r\reg
     .endr
@@ -26,21 +28,63 @@ save_sram_word:
     pop r11
     pop r10
     add #12, r1
+    eint
     ret
 
-asm_load_toc:
+asm_load_all:
+    dint
+
+    ; restore SRAM from backup
     mov #stack_backup, r10
     mov #1c00h, r11
-
 load_sram_word:
     mov @r10+, 0(r11)
     add #2, r11
     cmp #1c00h+2048, r11
     jlo load_sram_word
 
+    ; restore stack pointer
     mov &sp_backup, r1
+
+    ; restore registers
     .irp reg,11,10,9,8,7,6,5,4
     pop r\reg
     .endr
 
-    ret
\ No newline at end of file
+    eint
+
+    ; The return address on the stack has been restored from FRAM backup
+    ; -> execution will continue where asm_save_all was called
+    ret
+
+asm_load_mem:
+    dint
+    ; save return address in r4
+    mov @r1, r4
+
+    ; restore SRAM from backup
+    mov #stack_backup, r10
+    mov #1c00h, r11
+load_sram_word2:
+    mov @r10+, 0(r11)
+    add #2, r11
+    cmp #1c00h+2048, r11
+    jlo load_sram_word2
+
+    ; restore stack pointer
+    mov &sp_backup, r1
+
+    ; restore old register contents
+    .irp reg,11,10,9,8,7,6,5
+    pop r\reg
+    .endr
+
+    ; load return address, that is, the address this function was called from.
+    ; This is not the address which called asm_save_all -- we only want to restore memory contents, not re-execute everything
+    mov r4, 2(r1)
+
+    ; load remaining register content
+    pop r4
+
+    eint
+    ret